diff options
Diffstat (limited to 'src/gtkext/contentview.c')
-rw-r--r-- | src/gtkext/contentview.c | 1348 |
1 files changed, 1348 insertions, 0 deletions
diff --git a/src/gtkext/contentview.c b/src/gtkext/contentview.c new file mode 100644 index 0000000..0f93178 --- /dev/null +++ b/src/gtkext/contentview.c @@ -0,0 +1,1348 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * gtkdisplaypanel.c - affichage de contenus de binaire + * + * Copyright (C) 2016-2019 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "gtkdisplaypanel.h" + + +#include <math.h> + + +#include "gtkdisplaypanel-int.h" +#include "../glibext/chrysamarshal.h" +#include "../glibext/gbinarycursor.h" // REMME +#include "../glibext/gloadedpanel-int.h" + + + +/* Procède à l'initialisation de l'afficheur générique. */ +static void gtk_display_panel_class_init(GtkDisplayPanelClass *); + +/* Procède à l'initialisation de l'afficheur générique. */ +static void gtk_display_panel_init(GtkDisplayPanel *); + +/* Procède à l'initialisation de l'interface d'affichage. */ +static void gtk_display_panel_loaded_interface_init(GLoadedPanelInterface *); + +/* Supprime toutes les références externes. */ +static void gtk_display_panel_dispose(GtkDisplayPanel *); + +/* Procède à la libération totale de la mémoire. */ +static void gtk_display_panel_finalize(GtkDisplayPanel *); + +/* Définit une propriété du composant d'affichage. */ +static void gtk_display_panel_set_property(GObject *, guint, const GValue *, GParamSpec *); + +/* Fournit une propriété du composant d'affichage. */ +static void gtk_display_panel_get_property(GObject *, guint, GValue *, GParamSpec *); + +/* Détruit un composant d'affichage. */ +static void gtk_display_panel_destroy(GtkWidget *); + +/* Encadre la construction graphique initiale de l'affichage. */ +static void gtk_display_panel_realize(GtkWidget *); + +/* S'adapte à la surface concédée par le composant parent. */ +static void gtk_display_panel_size_allocate(GtkWidget *, GtkAllocation *); + +/* Fournit la hauteur idéale pour le composant d'affichage. */ +static void gtk_display_panel_get_preferred_height(GtkWidget *, gint *, gint *); + +/* Fournit la largeur idéale pour le composant d'affichage. */ +static void gtk_display_panel_get_preferred_width(GtkWidget *, gint *, gint *); + +/* Détermine la taille des bonds lors de défilements. */ +static void gtk_display_panel_compute_scroll_inc(GtkDisplayPanel *, gint, GtkOrientation, gdouble *, gdouble *); + +/* Détermine la taille allouée pour le contenu. */ +static void gtk_display_panel_compute_allocation(GtkDisplayPanel *, GtkAllocation *); + +/* Se débarrsse d'un ajustement pour un défilement donné. */ +static void gtk_display_panel_disconnect_adjustment(GtkDisplayPanel *, GtkOrientation); + +/* S'associe à un ajustement pour un défilement donné. */ +static void gtk_display_panel_set_adjustment(GtkDisplayPanel *, GtkOrientation, GtkAdjustment *); + +/* Ajuste les paramètres de défilement du composant. */ +static void gtk_display_panel_update_adjustment(GtkDisplayPanel *, GtkOrientation); + +/* Réagit à un défilement chez une barre associée au composant.*/ +static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *, GtkDisplayPanel *); + + + +/* ----------------------- INTERFACE DE PANNEAU DE CHARGEMENT ----------------------- */ + + +/* Réagit à un changement des règles d'affichage. */ +static void on_display_panel_option_change(GDisplayOptions *, size_t, bool, GtkDisplayPanel *); + +/* Associe à un panneau d'affichage un binaire chargé. */ +static void gtk_display_panel_set_content(GtkDisplayPanel *, GLoadedContent *); + +/* Fournit le contenu associé à un panneau de chargement. */ +static GLoadedContent *gtk_display_panel_get_content(const GtkDisplayPanel *); + +/* Fournit le position courante dans un panneau de chargement. */ +static GLineCursor *gtk_display_panel_get_cursor(const GtkDisplayPanel *); + +/* S'assure qu'un emplacement donné est visible à l'écran. */ +static void gtk_display_panel_scroll_to_cursor(GtkDisplayPanel *, const GLineCursor *, ScrollPositionTweak, bool); + +/* Place en cache un rendu destiné à l'aperçu graphique rapide. */ +static void gtk_display_panel_cache_glance(GtkDisplayPanel *, cairo_t *, const GtkAllocation *, double); + + + +/* Détermine le type du composant d'affichage générique. */ +G_DEFINE_TYPE_WITH_CODE(GtkDisplayPanel, gtk_display_panel, GTK_TYPE_FIXED, + G_IMPLEMENT_INTERFACE(GTK_TYPE_SCROLLABLE, NULL) + G_IMPLEMENT_INTERFACE(G_TYPE_LOADED_PANEL, gtk_display_panel_loaded_interface_init)); + + +/****************************************************************************** +* * +* Paramètres : class = classe GTK à initialiser. * +* * +* Description : Procède à l'initialisation de l'afficheur générique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_class_init(GtkDisplayPanelClass *class) +{ + GObjectClass *object; /* Plus haut niveau équivalent */ + GtkWidgetClass *widget; /* Classe de haut niveau */ + GtkDisplayPanelClass *panel; /* Classe de lus bas niveau */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)gtk_display_panel_dispose; + object->finalize = (GObjectFinalizeFunc)gtk_display_panel_finalize; + object->set_property = gtk_display_panel_set_property; + object->get_property = gtk_display_panel_get_property; + + /* Implémentation de l'interface "GtkScrollable" */ + g_object_class_override_property(object, VPP_HADJUSTMENT, "hadjustment"); + g_object_class_override_property(object, VPP_VADJUSTMENT, "vadjustment"); + g_object_class_override_property(object, VPP_HSCROLL_POLICY, "hscroll-policy"); + g_object_class_override_property(object, VPP_VSCROLL_POLICY, "vscroll-policy"); + + widget = GTK_WIDGET_CLASS(class); + + widget->destroy = gtk_display_panel_destroy; + widget->realize = gtk_display_panel_realize; + widget->size_allocate = gtk_display_panel_size_allocate; + widget->get_preferred_height = gtk_display_panel_get_preferred_height; + widget->get_preferred_width = gtk_display_panel_get_preferred_width; + + panel = GTK_DISPLAY_PANEL_CLASS(class); + + panel->compute_inc = gtk_display_panel_compute_scroll_inc; + + /* Signaux */ + + g_signal_new("scaled", + GTK_TYPE_DISPLAY_PANEL, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkDisplayPanelClass, scaled), + NULL, NULL, + g_cclosure_user_marshal_VOID__DOUBLE_DOUBLE, + G_TYPE_NONE, 2, G_TYPE_DOUBLE, G_TYPE_DOUBLE); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à initialiser. * +* * +* Description : Procède à l'initialisation de l'afficheur générique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_init(GtkDisplayPanel *panel) +{ + gtk_widget_set_has_window(GTK_WIDGET(panel), TRUE); + gtk_widget_set_can_focus(GTK_WIDGET(panel), TRUE); + + panel->scale = 1.0; + + panel->export = false; + +} + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_loaded_interface_init(GLoadedPanelInterface *iface) +{ + iface->set_content = (set_loaded_panel_content_fc)gtk_display_panel_set_content; + iface->get_content = (get_loaded_panel_content_fc)gtk_display_panel_get_content; + + iface->get_cursor = (get_loaded_cursor_fc)gtk_display_panel_get_cursor; + iface->scroll = (scroll_loaded_to_cursor_fc)gtk_display_panel_scroll_to_cursor; + + iface->cache_glance = (cache_loaded_glance_fc)gtk_display_panel_cache_glance; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_dispose(GtkDisplayPanel *panel) +{ + g_clear_object(&panel->hadjustment); + g_clear_object(&panel->vadjustment); + + g_clear_object(&panel->options); + + g_clear_object(&panel->binary); + + G_OBJECT_CLASS(gtk_display_panel_parent_class)->dispose(G_OBJECT(panel)); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_finalize(GtkDisplayPanel *panel) +{ + G_OBJECT_CLASS(gtk_display_panel_parent_class)->finalize(G_OBJECT(panel)); + +} + + +/****************************************************************************** +* * +* Paramètres : object = instance de composant GTK à manipuler. * +* prop_id = identifiant de la propriété concernée. * +* value = valeur attribuée. * +* pspec = spécification de la propriété visée. * +* * +* Description : Définit une propriété du composant d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GtkDisplayPanel *panel; /* Autre vision de l'instance */ + + panel = GTK_DISPLAY_PANEL(object); + + switch (prop_id) + { + case VPP_HADJUSTMENT: + gtk_display_panel_set_adjustment(panel, GTK_ORIENTATION_HORIZONTAL, g_value_get_object(value)); + break; + case VPP_VADJUSTMENT: + gtk_display_panel_set_adjustment(panel, GTK_ORIENTATION_VERTICAL, g_value_get_object(value)); + break; + case VPP_HSCROLL_POLICY: + //viewport->priv->hscroll_policy = g_value_get_enum (value); + //gtk_widget_queue_resize (GTK_WIDGET (viewport)); + break; + case VPP_VSCROLL_POLICY: + //viewport->priv->vscroll_policy = g_value_get_enum (value); + //gtk_widget_queue_resize (GTK_WIDGET (viewport)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } + +} + + +/****************************************************************************** +* * +* Paramètres : object = instance de composant GTK à manipuler. * +* prop_id = identifiant de la propriété concernée. * +* value = valeur à renvoyer. * +* pspec = spécification de la propriété visée. * +* * +* Description : Fournit une propriété du composant d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GtkDisplayPanel *panel; /* Autre vision de l'instance */ + + panel = GTK_DISPLAY_PANEL(object); + + switch (prop_id) + { + case VPP_HADJUSTMENT: + g_value_set_object(value, panel->hadjustment); + break; + case VPP_VADJUSTMENT: + g_value_set_object(value, panel->vadjustment); + break; + case VPP_HSCROLL_POLICY: + g_value_set_enum(value, panel->hscroll_policy); + break; + case VPP_VSCROLL_POLICY: + g_value_set_enum(value, panel->vscroll_policy); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à détruire. * +* * +* Description : Détruit un composant d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_destroy(GtkWidget *widget) +{ + GtkDisplayPanel *panel; /* Autre version du composant */ + + panel = GTK_DISPLAY_PANEL(widget); + + gtk_display_panel_disconnect_adjustment(panel, GTK_ORIENTATION_HORIZONTAL); + gtk_display_panel_disconnect_adjustment(panel, GTK_ORIENTATION_VERTICAL); + + GTK_WIDGET_CLASS(gtk_display_panel_parent_class)->destroy(widget); + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à préparer. * +* * +* Description : Encadre la construction graphique initiale de l'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_realize(GtkWidget *widget) +{ + GtkAllocation allocation; /* Disposition du composant */ + GdkWindowAttr attributes; /* Propriétés du composant */ + guint attributes_mask; /* Masque de prise en compte */ + GdkWindow *window; /* Fenêtre du composant */ + + gtk_widget_get_allocation(widget, &allocation); + + gtk_widget_set_realized(widget, TRUE); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = allocation.x; + attributes.y = allocation.y; + attributes.width = allocation.width; + attributes.height = allocation.height; + + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.event_mask = gtk_widget_get_events(widget) + | GDK_EXPOSURE_MASK + | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK + | GDK_FOCUS_CHANGE_MASK + | GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + window = gdk_window_new(gtk_widget_get_parent_window(widget), + &attributes, attributes_mask); + + gtk_widget_set_window(widget, window); + gtk_widget_register_window(widget, window); + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à mettre à jour. * +* allocation = étendue accordée à la vue. * +* * +* Description : S'adapte à la surface concédée par le composant parent. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +{ + GtkDisplayPanel *panel; /* Autre version du composant */ + + GTK_WIDGET_CLASS(gtk_display_panel_parent_class)->size_allocate(widget, allocation); + + panel = GTK_DISPLAY_PANEL(widget); + + gtk_display_panel_update_adjustment(panel, GTK_ORIENTATION_HORIZONTAL); + gtk_display_panel_update_adjustment(panel, GTK_ORIENTATION_VERTICAL); + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à examiner. * +* minimum = hauteur minimale à préciser ou NULL. [OUT] * +* natural = hauteur idéale à préciser ou NULL. [OUT] * +* * +* Description : Fournit la hauteur idéale pour le composant d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_get_preferred_height(GtkWidget *widget, gint *minimum, gint *natural) +{ + GtkDisplayPanel *panel; /* Autre version du composant */ + gint req; /* Dimension requise */ + + panel = GTK_DISPLAY_PANEL(widget); + + GTK_DISPLAY_PANEL_GET_CLASS(widget)->compute_size(panel, NULL, &req); + + req *= panel->scale; + + if (minimum != NULL) *minimum = req; + if (natural != NULL) *natural = req; + +} + + +/****************************************************************************** +* * +* Paramètres : widget = composant GTK à examiner. * +* minimum = largeur minimale à préciser ou NULL. [OUT] * +* natural = largeur idéale à préciser ou NULL. [OUT] * +* * +* Description : Fournit la largeur idéale pour le composant d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural) +{ + GtkDisplayPanel *panel; /* Autre version du composant */ + gint req; /* Dimension requise */ + + panel = GTK_DISPLAY_PANEL(widget); + + GTK_DISPLAY_PANEL_GET_CLASS(widget)->compute_size(panel, &req, NULL); + + req *= panel->scale; + + if (minimum != NULL) *minimum = req; + if (natural != NULL) *natural = req; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK d'affichage à mettre à jour. * +* size = taille de l'espace dans la direction donnée. * +* orientation = indication sur le défilement à traiter. * +* step = valeur d'un petit pas de défilement. [OUT] * +* page = valeur d'un grand pas de défilement. [OUT] * +* * +* Description : Détermine la taille des bonds lors de défilements. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_compute_scroll_inc(GtkDisplayPanel *panel, gint size, GtkOrientation orientation, gdouble *step, gdouble *page) +{ + *step = size * 0.1; + *page = size * 0.9; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à consulter. * +* alloc = emplacement à déterminer. [OUT] * +* * +* Description : Détermine la taille allouée pour le contenu. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_compute_allocation(GtkDisplayPanel *panel, GtkAllocation *alloc) +{ + GtkWidget *widget; /* Autre vision du composant */ + GtkAllocation allocation; /* Emplacement du composant */ + GtkStyleContext *context; /* Contexte du style */ + GtkStateFlags state; /* Etat du composant */ + GtkBorder padding; /* Espace d'un espacement */ + GtkBorder border; /* Espace d'une bordure */ + + widget = GTK_WIDGET(panel); + + gtk_widget_get_allocation(widget, &allocation); + + context = gtk_widget_get_style_context(widget); + state = gtk_widget_get_state_flags(widget); + + gtk_style_context_save(context); + gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME); + + gtk_style_context_get_padding(context, state, &padding); + gtk_style_context_get_border(context, state, &border); + + gtk_style_context_restore(context); + + /* Positions */ + + if (panel->show_border) + { + alloc->x = border.left; + alloc->y = border.top; + } + else + { + alloc->x = 0; + alloc->y = 0; + } + + alloc->x += padding.left; + alloc->y += padding.top; + + /* Dimensions */ + + if (panel->show_border) + { + alloc->width = MAX (1, allocation.width - alloc->x - padding.right - border.right); + alloc->height = MAX (1, allocation.height - alloc->y - padding.bottom - border.bottom); + } + else + { + alloc->width = MAX (1, allocation.width - alloc->x - padding.right); + alloc->height = MAX (1, allocation.height - alloc->y - padding.bottom); + } + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK d'affichage à mettre à jour. * +* orientation = indication sur le défilement à traiter. * +* * +* Description : Se débarrsse d'un ajustement pour un défilement donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_disconnect_adjustment(GtkDisplayPanel *panel, GtkOrientation orientation) +{ + GtkAdjustment **adjp; /* Ajustement à manipuler */ + + adjp = orientation == GTK_ORIENTATION_HORIZONTAL ? &panel->hadjustment : &panel->vadjustment; + + if (*adjp != NULL) + { + g_signal_handlers_disconnect_by_func(*adjp, gtk_display_panel_adjustment_value_changed, panel); + g_object_unref(G_OBJECT(*adjp)); + *adjp = NULL; + } + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK d'affichage à mettre à jour. * +* orientation = indication sur le défilement à traiter. * +* adj = nouvel ajustement à prendre en compte. * +* * +* Description : S'associe à un ajustement pour un défilement donné. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_set_adjustment(GtkDisplayPanel *panel, GtkOrientation orientation, GtkAdjustment *adj) +{ + GtkAdjustment **adjp; /* Ajustement à manipuler */ + + adjp = orientation == GTK_ORIENTATION_HORIZONTAL ? &panel->hadjustment : &panel->vadjustment; + + /* S'il n'y a rien à faire... */ + if (adj != NULL && adj == *adjp) + return; + + if (!adj) + adj = gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + + gtk_display_panel_disconnect_adjustment(panel, orientation); + + *adjp = adj; + g_object_ref_sink(adj); + + gtk_display_panel_update_adjustment(panel, orientation); + + g_signal_connect(adj, "value-changed", G_CALLBACK(gtk_display_panel_adjustment_value_changed), panel); + + gtk_display_panel_adjustment_value_changed(adj, panel); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK d'affichage à mettre à jour. * +* orientation = indication sur le défilement à traiter. * +* * +* Description : Ajuste les paramètres de défilement du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_update_adjustment(GtkDisplayPanel *panel, GtkOrientation orientation) +{ + GtkAllocation allocation; /* Emplacement du contenu */ + GtkAdjustment *adj; /* Ajustement à manipuler */ + gint req; /* Dimension requise */ + gint allocated; /* Dimension allouée */ + gdouble step_inc; /* Pas de défilement */ + gdouble page_inc; /* ENjambée de défilement */ + + gtk_display_panel_compute_allocation(panel, &allocation); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + adj = panel->hadjustment; + + gtk_widget_get_preferred_width(GTK_WIDGET(panel), &req, NULL); + allocated = allocation.width; + + } + else + { + adj = panel->vadjustment; + + gtk_widget_get_preferred_height(GTK_WIDGET(panel), &req, NULL); + allocated = allocation.height; + + } + + GTK_DISPLAY_PANEL_GET_CLASS(panel)->compute_inc(panel, allocated, orientation, &step_inc, &page_inc); + + gtk_adjustment_configure(adj, gtk_adjustment_get_value(adj), + 0, MAX(req, allocated), + step_inc, + page_inc, + allocated); + +} + + +/****************************************************************************** +* * +* Paramètres : adj = défilement dont une valeur a changé. * +* panel = panneau d'affichage concerné. * +* * +* Description : Réagit à un défilement chez une barre associée au composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *adj, GtkDisplayPanel *panel) +{ + GtkOrientation orientation; /* Indification de la barre */ + + orientation = (adj == panel->hadjustment ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); + + if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->adjust != NULL) + GTK_DISPLAY_PANEL_GET_CLASS(panel)->adjust(panel, adj, orientation); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à mettre à jour. * +* * +* Description : Indique l'échelle appliquée à l'affichage du composant. * +* * +* Retour : Echelle appliquée à l'affichage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +double gtk_display_panel_get_scale(const GtkDisplayPanel *panel) +{ + double result; /* Echelle à retourner */ + + result = panel->scale; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à mettre à jour. * +* scale = échelle appliquée à l'affichage. * +* * +* Description : Spécifie l'échelle à appliquer à l'affichage du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_set_scale(GtkDisplayPanel *panel, double scale) +{ + double old_scale; /* Echelle précédente */ + GtkDisplayPanelClass *class; /* Classe associée au composant*/ + + if (scale > 1.0) + scale = 1.0; + + else if (scale < 0.01) + scale = 0.01; + + if (panel->scale != scale) + { + old_scale = panel->scale; + + panel->scale = scale; + + class = GTK_DISPLAY_PANEL_GET_CLASS(panel); + + if (class->scale != NULL) + class->scale(panel, old_scale, scale); + + gtk_widget_queue_resize(GTK_WIDGET(panel)); + + g_signal_emit_by_name(panel, "scaled", old_scale, scale); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à mettre à jour. * +* show = état de l'affichage auquel parvenir. * +* * +* Description : Définit si une bordure est à afficher. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_show_border(GtkDisplayPanel *panel, bool show) +{ + panel->show_border = show; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à mettre à jour. * +* export = préparation d'une exportation complète du rendu ? * +* * +* Description : Marque ou non le composant pour une exportation prochaine. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_prepare_export(GtkDisplayPanel *panel, bool export) +{ + GtkDisplayPanelClass *class; /* Classe associée au composant*/ + + panel->export = export; + + class = GTK_DISPLAY_PANEL_GET_CLASS(panel); + + if (class->prepare_export != NULL) + class->prepare_export(panel, export); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à venir consulter. * +* cr = contexte graphique associé à l'événement. * +* area = surface à considérer. * +* * +* Description : Définit un chemin décrivant la bordure autour du panneau. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_define_border_path(GtkDisplayPanel *panel, cairo_t *cr, const GtkAllocation *area) +{ + double degrees; /* Conversion en degrés */ + + degrees = M_PI / 180.0; + + cairo_new_sub_path(cr); + + cairo_arc(cr, + area->x + area->width - BORDER_CORNER_RADIUS - 0.5, + area->y + BORDER_CORNER_RADIUS + 0.5, + BORDER_CORNER_RADIUS, -90 * degrees, 0 * degrees); + + cairo_arc(cr, + area->x + area->width - BORDER_CORNER_RADIUS - 0.5, + area->y + area->height - BORDER_CORNER_RADIUS - 0.5, + BORDER_CORNER_RADIUS, 0 * degrees, 90 * degrees); + + cairo_arc(cr, + area->x + BORDER_CORNER_RADIUS + 0.5, + area->y + area->height - BORDER_CORNER_RADIUS - 0.5, + BORDER_CORNER_RADIUS, 90 * degrees, 180 * degrees); + + cairo_arc(cr, + area->x + BORDER_CORNER_RADIUS + 0.5, + area->y + BORDER_CORNER_RADIUS + 0.5, + BORDER_CORNER_RADIUS, 180 * degrees, 270 * degrees); + + cairo_close_path(cr); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à venir consulter. * +* cr = contexte graphique associé à l'événement. * +* * +* Description : Dessine si besoin est une bordure autour du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_draw_border(GtkDisplayPanel *panel, cairo_t *cr) +{ + GtkWidget *widget; /* Autre version du composant */ + GtkStyleContext *context; /* Contexte du thème actuel */ + GdkRGBA color; /* Couleur de thème récupérée */ + GtkRequisition req; /* Taille allouée à l'élément */ + GtkAllocation area; /* Emplacement à considérer */ + + if (panel->show_border) + { + widget = GTK_WIDGET(panel); + + gtk_widget_get_preferred_size(widget, NULL, &req); + + context = gtk_widget_get_style_context(widget); + + gtk_style_context_save(context); + + gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME); + + gtk_style_context_get(gtk_widget_get_style_context(widget), + gtk_widget_get_state_flags(widget), + GTK_STYLE_PROPERTY_COLOR, &color, NULL); + + cairo_set_source_rgba(cr, color.red, color.green, color.blue, color.alpha); + + cairo_set_line_width(cr, 1.0); + + gtk_widget_get_preferred_size(GTK_WIDGET(panel), NULL, &req); + + area.x = 0; + area.y = 0; + area.width = req.width; + area.height = req.height; + + gtk_display_panel_define_border_path(panel, cr, &area); + cairo_stroke(cr); + + gtk_style_context_restore(context); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à consulter. * +* cursor = emplacement à présenter à l'écran. * +* x = position horizontale au sein du composant. [OUT] * +* y = position verticale au sein du composant. [OUT] * +* tweak = adaptation finale à effectuer. * +* * +* Description : Indique la position d'affichage d'un emplacement donné. * +* * +* Retour : true si l'adresse fait partie du composant, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool gtk_display_panel_get_cursor_coordinates(const GtkDisplayPanel *panel, const GLineCursor *cursor, gint *x, gint *y, ScrollPositionTweak tweak) +{ + bool result; /* Bilan à remonter */ + + result = GTK_DISPLAY_PANEL_GET_CLASS(panel)->get_coordinates(panel, cursor, x, y, tweak); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à consulter. * +* * +* Description : Fournit l'élément actif lié à la position courante. * +* * +* Retour : Objet actif courant ou NULL si aucun. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GObject *gtk_display_panel_get_active_object(const GtkDisplayPanel *panel) +{ + GObject *result; /* Trouvaille à retourner */ + + if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->get_active == NULL) + result = NULL; + + else + result = GTK_DISPLAY_PANEL_GET_CLASS(panel)->get_active(panel); + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à manipuler. * +* addr = adresse à présenter à l'écran. * +* * +* Description : Demande à qui veut répondre un déplacement du curseur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_request_move(GtkDisplayPanel *panel, const vmpa2t *addr) +{ + GLineCursor *___tmp; + + ___tmp = g_binary_cursor_new(); + g_binary_cursor_update(G_BINARY_CURSOR(___tmp), addr); + + g_loaded_panel_request_move(G_LOADED_PANEL(panel), ___tmp, false); + + g_object_unref(G_OBJECT(___tmp)); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à consulter. * +* event = informations liées à l'événement. * +* * +* Description : Transcrit les coordonnées à l'écran en coordonnées absolues. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_compute_fake_coord(GtkDisplayPanel *panel, gint *x, gint *y) +{ + if (panel->hadjustment != NULL) + *x -= gtk_adjustment_get_value(panel->hadjustment); + + if (panel->vadjustment != NULL) + *y += gtk_adjustment_get_value(panel->vadjustment); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à consulter. * +* event = informations liées à l'événement. * +* * +* Description : Transcrit les coordonnées absolues en coordonnées à l'écran. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_compute_real_coord(GtkDisplayPanel *panel, gint *x, gint *y) +{ + if (x != NULL && panel->hadjustment != NULL) + *x += gtk_adjustment_get_value(panel->hadjustment); + + if (y != NULL && panel->vadjustment != NULL) + *y += gtk_adjustment_get_value(panel->vadjustment); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à consulter. * +* x = abscisse à ajuster. [OUT] * +* x = ordonnée à ajuster. [OUT] * +* * +* Description : Transcrit les coordonnées absolues en coordonnées à l'écran. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_display_panel_compute_relative_coords(GtkDisplayPanel *panel, gint *x, gint *y) +{ + if (x != NULL && panel->hadjustment != NULL) + *x -= gtk_adjustment_get_value(panel->hadjustment); + + if (y != NULL && panel->vadjustment != NULL) + *y -= gtk_adjustment_get_value(panel->vadjustment); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* INTERFACE DE PANNEAU DE CHARGEMENT */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : options = options à mettre à jour. * +* index = indice de l'option concernée. * +* value = nouvelle valeur à intégrer. * +* panel = composant GTK à consulter. * +* * +* Description : Réagit à un changement des règles d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_display_panel_option_change(GDisplayOptions *options, size_t index, bool value, GtkDisplayPanel *panel) +{ + gtk_widget_queue_resize(gtk_widget_get_parent(GTK_WIDGET(panel))); + gtk_widget_queue_resize(GTK_WIDGET(panel)); + gtk_widget_queue_draw(GTK_WIDGET(panel)); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à mettre à jour. * +* content = binaire associé à intégrer. * +* * +* Description : Associe à un panneau d'affichage un binaire chargé. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_set_content(GtkDisplayPanel *panel, GLoadedContent *content) +{ + panel->view_index = g_loaded_content_get_view_index(content, GTK_WIDGET(panel)); + + panel->options = g_loaded_content_get_display_options(content, panel->view_index); + + panel->binary = G_LOADED_BINARY(content); + + g_signal_connect(panel->options, "value-changed", G_CALLBACK(on_display_panel_option_change), panel); + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à consulter. * +* * +* Description : Fournit le contenu associé à un panneau de chargement. * +* * +* Retour : Contenu quelconque chargé en mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GLoadedContent *gtk_display_panel_get_content(const GtkDisplayPanel *panel) +{ + GLoadedContent *result; /* Contenu à retourner */ + + result = G_LOADED_CONTENT(panel->binary); + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à consulter. * +* * +* Description : Fournit le position courante dans un panneau de chargement. * +* * +* Retour : Informations relatives à la position du curseur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GLineCursor *gtk_display_panel_get_cursor(const GtkDisplayPanel *panel) +{ + GLineCursor *result; /* Contenu à retourner */ + + result = GTK_DISPLAY_PANEL_GET_CLASS(panel)->get_cursor(panel); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à manipuler. * +* cursor = emplacement à présenter à l'écran. * +* tweak = adaptation finale à effectuer. * +* move = doit-on déplacer le curseur à l'adresse indiquée ? * +* * +* Description : S'assure qu'un emplacement donné est visible à l'écran. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_scroll_to_cursor(GtkDisplayPanel *panel, const GLineCursor *cursor, ScrollPositionTweak tweak, bool move) +{ + GtkWidget *parent; /* Support parent à valider */ + GtkDisplayPanelClass *class; /* Classe de l'instance */ + gint x; /* Abscisse à garantir */ + gint y; /* Ordonnée à garantir */ + GtkWidget *viewport; /* Parent avec défilement */ + GtkAdjustment *adj; /* Défilement à mettre à jour */ + gdouble step_inc; /* Valeur d'un petit pas */ + gdouble page_size; /* Taille de l'affichage */ + double value; /* Valeur courante */ + + /** + * Si une vue partielle se déplace via cette fonction, il faut potentiellement + * rediriger l'appel vers la vue en graphiques parente. + */ + + parent = gtk_widget_get_parent(GTK_WIDGET(panel)); + parent = gtk_widget_get_parent(GTK_WIDGET(parent)); + + if (GTK_IS_DISPLAY_PANEL(parent)) + panel = GTK_DISPLAY_PANEL(parent); + + class = GTK_DISPLAY_PANEL_GET_CLASS(panel); + + if (class->prepare != NULL) + class->prepare(panel, cursor); + + if (gtk_display_panel_get_cursor_coordinates(panel, cursor, &x, &y, tweak)) + { + viewport = gtk_widget_get_parent(GTK_WIDGET(panel)); + + /* Eventuel défilement horizontal */ + + g_object_get(G_OBJECT(viewport), "hadjustment", &adj, NULL); + + step_inc = gtk_adjustment_get_step_increment(adj); + page_size = gtk_adjustment_get_page_size(adj); + value = gtk_adjustment_get_value(adj); + + if (x < value) + gtk_adjustment_set_value(adj, x); + + else if ((x + step_inc) > (value + page_size)) + gtk_adjustment_set_value(adj, x + step_inc - page_size); + + /* Eventuel défilement vertical */ + + g_object_get(G_OBJECT(viewport), "vadjustment", &adj, NULL); + + step_inc = gtk_adjustment_get_step_increment(adj); + page_size = gtk_adjustment_get_page_size(adj); + value = gtk_adjustment_get_value(adj); + + if (y < value || tweak != SPT_RAW) + gtk_adjustment_set_value(adj, y); + + else if ((y + step_inc) > (value + page_size)) + gtk_adjustment_set_value(adj, y + step_inc - page_size); + + /* Déplacement du curseur */ + + if (move && gtk_display_panel_get_cursor_coordinates(panel, cursor, &x, &y, SPT_RAW)) + class->move_caret_to(panel, x, y); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : panel = composant GTK à manipuler. * +* cairo = assistant pour la création de rendus. * +* area = taille de la surface réduite à disposition. * +* scale = échelle vis à vis de la taille réelle. * +* * +* Description : Place en cache un rendu destiné à l'aperçu graphique rapide. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_display_panel_cache_glance(GtkDisplayPanel *panel, cairo_t *cairo, const GtkAllocation *area, double scale) +{ + if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->cache_glance != NULL) + GTK_DISPLAY_PANEL_GET_CLASS(panel)->cache_glance(panel, cairo, area, scale); + +} |