From ff1ce15f6c4b3516d7a34b09dd99abb32a0bd671 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 21 Mar 2019 00:04:32 +0100 Subject: Introduced zoom in graph view. --- configure.ac | 2 +- src/glibext/gbufferview.c | 5 +- src/glibext/gbufferview.h | 2 +- src/gtkext/gtkbufferdisplay.c | 18 ++++- src/gtkext/gtkdisplaypanel-int.h | 13 +++- src/gtkext/gtkdisplaypanel.c | 137 +++++++++++++++++++++++++++++++++------ src/gtkext/gtkdisplaypanel.h | 6 ++ src/gtkext/gtkgraphdisplay.c | 129 ++++++++++++++++++++++++++++++++---- src/gui/menus/menubar.c | 2 +- src/gui/menus/view.c | 93 +++++++++++++++++++++++++- src/gui/menus/view.h | 2 +- 11 files changed, 361 insertions(+), 48 deletions(-) diff --git a/configure.ac b/configure.ac index 1f50fd0..a2d8b5e 100644 --- a/configure.ac +++ b/configure.ac @@ -365,7 +365,7 @@ AC_SUBST(LIBPYGOBJECT_LIBS) AC_CONFIG_FILES([stamp-h po/Makefile.in], [echo timestamp > stamp-h]) -AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64\nVOID:INT,UINT64,INT\nVOID:OBJECT,OBJECT\nVOID:ENUM,OBJECT\nVOID:ENUM,ENUM\nVOID:BOOLEAN,UINT64\nVOID:BOOLEAN,ULONG,ULONG\nVOID:INT,INT\nVOID:OBJECT,BOOLEAN\nVOID:ULONG,BOOLEAN" > src/glibext/chrysamarshal.list]) +AC_CONFIG_COMMANDS([marshal], [echo -e "VOID:UINT64\nVOID:INT,UINT64,INT\nVOID:OBJECT,OBJECT\nVOID:ENUM,OBJECT\nVOID:ENUM,ENUM\nVOID:BOOLEAN,UINT64\nVOID:BOOLEAN,ULONG,ULONG\nVOID:INT,INT\nVOID:OBJECT,BOOLEAN\nVOID:ULONG,BOOLEAN\nVOID:DOUBLE,DOUBLE" > src/glibext/chrysamarshal.list]) AC_CONFIG_FILES([Makefile doc/Makefile diff --git a/src/glibext/gbufferview.c b/src/glibext/gbufferview.c index c5021f2..db8da28 100644 --- a/src/glibext/gbufferview.c +++ b/src/glibext/gbufferview.c @@ -1100,6 +1100,7 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const G * options = règles d'affichage des colonnes modulables. * * offsets = décalages supplémentaires à appliquer. * * selected = ordonnée d'une ligne sélectionnée ou NULL. * +* scale = échelle appliquée à la surface de rendu. * * export = indique si la vue est en cours d'exportation. * * * * Description : Imprime la visualisation du tampon de lignes quelconques. * @@ -1110,7 +1111,7 @@ bool g_buffer_view_highlight_segments(GBufferView *view, gint x, gint y, const G * * ******************************************************************************/ -void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const GDisplayOptions *options, const line_width_summary *offsets, gint *selected, bool export) +void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const cairo_rectangle_int_t *area, const GDisplayOptions *options, const line_width_summary *offsets, gint *selected, double scale, bool export) { gint line_height; /* Hauteur d'une ligne */ gint cr_y; /* Ordonnée pour le dessin */ @@ -1118,7 +1119,7 @@ void g_buffer_view_draw(const GBufferView *view, cairo_t *cr, gint virt_y, const size_t last; /* Dernière ligne visée */ segcnt_list *highlighted; /* Segments mis en évidence */ - line_height = g_buffer_cache_get_line_height(view->cache); + line_height = g_buffer_cache_get_line_height(view->cache) * scale; /* Indice et point de départ */ diff --git a/src/glibext/gbufferview.h b/src/glibext/gbufferview.h index 9d40cbd..c6cc5aa 100644 --- a/src/glibext/gbufferview.h +++ b/src/glibext/gbufferview.h @@ -98,7 +98,7 @@ bool g_buffer_view_unhighlight_segments(GBufferView *); bool g_buffer_view_highlight_segments(GBufferView *, gint, gint, const GDisplayOptions *, const line_width_summary *); /* Imprime la visualisation du tampon de lignes quelconques. */ -void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const GDisplayOptions *, const line_width_summary *, gint *, bool); +void g_buffer_view_draw(const GBufferView *, cairo_t *, gint, const cairo_rectangle_int_t *, const GDisplayOptions *, const line_width_summary *, gint *, double, bool); diff --git a/src/gtkext/gtkbufferdisplay.c b/src/gtkext/gtkbufferdisplay.c index b9784de..b7af1d6 100644 --- a/src/gtkext/gtkbufferdisplay.c +++ b/src/gtkext/gtkbufferdisplay.c @@ -423,8 +423,14 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) if (parent->show_border) { - gtk_display_panel_define_border_path(parent, cr, 0, 0); + gtk_widget_get_allocation(widget, &allocation); + + allocation.x = 0; + allocation.y = 0; + + gtk_display_panel_define_border_path(parent, cr, &allocation); cairo_clip(cr); + } /* Décalage pour le défilement horizontal */ @@ -441,7 +447,7 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) cache = g_buffer_view_get_cache(display->view); - left_margin = g_buffer_cache_get_left_margin(cache); + left_margin = g_buffer_cache_get_left_margin(cache) * parent->scale; g_object_unref(G_OBJECT(cache)); @@ -494,6 +500,10 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) /* Impression du désassemblage */ + cairo_save(cr); + + cairo_scale(cr, parent->scale, parent->scale); + if (display->view != NULL) { g_generic_config_get_value(get_main_configuration(), MPK_SELECTION_LINE, &sel_line); @@ -511,7 +521,7 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) virt_y += area.y; g_buffer_view_draw(display->view, cr, virt_y, &area, parent->options, &display->offsets, - selected, parent->export); + selected, parent->scale, parent->export); } @@ -528,6 +538,8 @@ static gboolean gtk_buffer_display_draw(GtkWidget *widget, cairo_t *cr) GTK_WIDGET_CLASS(gtk_buffer_display_parent_class)->draw(widget, cr); + cairo_restore(cr); + return FALSE; } diff --git a/src/gtkext/gtkdisplaypanel-int.h b/src/gtkext/gtkdisplaypanel-int.h index 7be5616..17fd6f0 100644 --- a/src/gtkext/gtkdisplaypanel-int.h +++ b/src/gtkext/gtkdisplaypanel-int.h @@ -71,6 +71,9 @@ typedef GLineCursor * (* get_cursor_fc) (const GtkDisplayPanel *); /* Place en cache un rendu destiné à l'aperçu graphique rapide. */ typedef void (* cache_glance_fc) (GtkDisplayPanel *, cairo_t *, const GtkAllocation *, double); +/* Spécifie l'échelle à appliquer à l'affichage du composant. */ +typedef void (* apply_scale_fc) (GtkDisplayPanel *, double, double); + /* Marque ou non le composant pour une exportation prochaine. */ typedef void (* prepare_export_fc) (GtkDisplayPanel *, bool); @@ -86,6 +89,8 @@ struct _GtkDisplayPanel GtkScrollablePolicy hscroll_policy; /* Politique horizontale */ GtkScrollablePolicy vscroll_policy; /* Politique verticale */ + double scale; /* Echelle de l'affichage */ + bool show_border; /* Affichage d'une bordure ? */ unsigned int view_index; /* Indice du type de contenu */ GDisplayOptions *options; /* Affichage des colonnes ? */ @@ -112,8 +117,14 @@ struct _GtkDisplayPanelClass get_cursor_fc get_cursor; /* Fourniture d'une position */ cache_glance_fc cache_glance; /* Cache de la mignature */ + apply_scale_fc scale; /* Mise à jour de l'échelle */ + prepare_export_fc prepare_export; /* Préparation d'exportation */ + /* Signaux */ + + void (* scaled) (GtkDisplayPanel *, double, double); + }; /* Propriétés propres au composant d'affichage */ @@ -129,7 +140,7 @@ typedef enum _ViewPanelProps /* Définit un chemin décrivant la bordure autour du panneau. */ -void gtk_display_panel_define_border_path(GtkDisplayPanel *, cairo_t *, gint, gint); +void gtk_display_panel_define_border_path(GtkDisplayPanel *, cairo_t *, const GtkAllocation *); /* Dessine si besoin est une bordure autour du composant. */ void gtk_display_panel_draw_border(GtkDisplayPanel *, cairo_t *); diff --git a/src/gtkext/gtkdisplaypanel.c b/src/gtkext/gtkdisplaypanel.c index b32adfa..76c18ec 100644 --- a/src/gtkext/gtkdisplaypanel.c +++ b/src/gtkext/gtkdisplaypanel.c @@ -28,6 +28,7 @@ #include "gtkdisplaypanel-int.h" +#include "../glibext/chrysamarshal.h" #include "../glibext/gbinarycursor.h" // REMME #include "../glibext/gloadedpanel-int.h" @@ -161,6 +162,16 @@ static void gtk_display_panel_class_init(GtkDisplayPanelClass *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); + } @@ -181,6 +192,8 @@ 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; } @@ -460,9 +473,14 @@ static void gtk_display_panel_size_allocate(GtkWidget *widget, GtkAllocation *al static void gtk_display_panel_get_preferred_height(GtkWidget *widget, gint *minimum, gint *natural) { + GtkDisplayPanel *panel; /* Autre version du composant */ gint req; /* Dimension requise */ - GTK_DISPLAY_PANEL_GET_CLASS(widget)->compute_size(GTK_DISPLAY_PANEL(widget), NULL, &req); + 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; @@ -486,9 +504,14 @@ static void gtk_display_panel_get_preferred_height(GtkWidget *widget, gint *mini static void gtk_display_panel_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural) { + GtkDisplayPanel *panel; /* Autre version du composant */ gint req; /* Dimension requise */ - GTK_DISPLAY_PANEL_GET_CLASS(widget)->compute_size(GTK_DISPLAY_PANEL(widget), &req, NULL); + 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; @@ -687,7 +710,7 @@ static void gtk_display_panel_update_adjustment(GtkDisplayPanel *panel, GtkOrien { adj = panel->hadjustment; - GTK_DISPLAY_PANEL_GET_CLASS(panel)->compute_size(panel, &req, NULL); + gtk_widget_get_preferred_width(GTK_WIDGET(panel), &req, NULL); allocated = allocation.width; } @@ -695,7 +718,7 @@ static void gtk_display_panel_update_adjustment(GtkDisplayPanel *panel, GtkOrien { adj = panel->vadjustment; - GTK_DISPLAY_PANEL_GET_CLASS(panel)->compute_size(panel, NULL, &req); + gtk_widget_get_preferred_height(GTK_WIDGET(panel), &req, NULL); allocated = allocation.height; } @@ -739,6 +762,73 @@ static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *adj, GtkDi /****************************************************************************** * * * 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. * @@ -785,9 +875,9 @@ void gtk_display_panel_prepare_export(GtkDisplayPanel *panel, bool export) /****************************************************************************** * * -* Paramètres : panel = composant GTK à venir consulter. * -* cr = contexte graphique associé à l'événement. * -* offset = décalage éventuel à appliquer. * +* 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. * * * @@ -797,35 +887,32 @@ void gtk_display_panel_prepare_export(GtkDisplayPanel *panel, bool export) * * ******************************************************************************/ -void gtk_display_panel_define_border_path(GtkDisplayPanel *panel, cairo_t *cr, gint off_x, gint off_y) +void gtk_display_panel_define_border_path(GtkDisplayPanel *panel, cairo_t *cr, const GtkAllocation *area) { - GtkRequisition req; /* Taille allouée à l'élément */ double degrees; /* Conversion en degrés */ - gtk_widget_get_preferred_size(GTK_WIDGET(panel), NULL, &req); - degrees = M_PI / 180.0; cairo_new_sub_path(cr); cairo_arc(cr, - off_x + req.width - BORDER_CORNER_RADIUS - 0.5, - off_y + BORDER_CORNER_RADIUS + 0.5, + 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, - off_x + req.width - BORDER_CORNER_RADIUS - 0.5, - off_y + req.height - BORDER_CORNER_RADIUS - 0.5, + 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, - off_x + BORDER_CORNER_RADIUS + 0.5, - off_y + req.height - BORDER_CORNER_RADIUS - 0.5, + 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, - off_x + BORDER_CORNER_RADIUS + 0.5, - off_y + BORDER_CORNER_RADIUS + 0.5, + 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); @@ -849,9 +936,10 @@ void gtk_display_panel_define_border_path(GtkDisplayPanel *panel, cairo_t *cr, g void gtk_display_panel_draw_border(GtkDisplayPanel *panel, cairo_t *cr) { GtkWidget *widget; /* Autre version du composant */ - GtkRequisition req; /* Taille allouée à l'élément */ 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) { @@ -873,7 +961,14 @@ void gtk_display_panel_draw_border(GtkDisplayPanel *panel, cairo_t *cr) cairo_set_line_width(cr, 1.0); - gtk_display_panel_define_border_path(panel, cr, 0, 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); diff --git a/src/gtkext/gtkdisplaypanel.h b/src/gtkext/gtkdisplaypanel.h index 937d41d..9f58b87 100644 --- a/src/gtkext/gtkdisplaypanel.h +++ b/src/gtkext/gtkdisplaypanel.h @@ -52,6 +52,12 @@ typedef struct _GtkDisplayPanelClass GtkDisplayPanelClass; /* Détermine le type du composant d'affichage générique. */ GType gtk_display_panel_get_type(void); +/* Indique l'échelle appliquée à l'affichage du composant. */ +double gtk_display_panel_get_scale(const GtkDisplayPanel *); + +/* Spécifie l'échelle à appliquer à l'affichage du composant. */ +void gtk_display_panel_set_scale(GtkDisplayPanel *, double); + /* Définit si une bordure est à afficher. */ void gtk_display_panel_show_border(GtkDisplayPanel *, bool); diff --git a/src/gtkext/gtkgraphdisplay.c b/src/gtkext/gtkgraphdisplay.c index 97bb4d3..aeecc0f 100644 --- a/src/gtkext/gtkgraphdisplay.c +++ b/src/gtkext/gtkgraphdisplay.c @@ -146,6 +146,9 @@ static GLineCursor *gtk_graph_display_get_cursor(const GtkGraphDisplay *); /* Place en cache un rendu destiné à l'aperçu graphique rapide. */ static void gtk_graph_display_cache_glance(GtkGraphDisplay *, cairo_t *, const GtkAllocation *, double); +/* Spécifie l'échelle à appliquer à l'affichage du composant. */ +static void gtk_graph_display_apply_scale(GtkGraphDisplay *, double, double); + /* Marque ou non le composant pour une exportation prochaine. */ static void gtk_graph_display_prepare_export(GtkGraphDisplay *, bool); @@ -205,6 +208,8 @@ static void gtk_graph_display_class_init(GtkGraphDisplayClass *class) panel_class->get_cursor = (get_cursor_fc)gtk_graph_display_get_cursor; panel_class->cache_glance = (cache_glance_fc)gtk_graph_display_cache_glance; + panel_class->scale = (apply_scale_fc)gtk_graph_display_apply_scale; + panel_class->prepare_export = (prepare_export_fc)gtk_graph_display_prepare_export; } @@ -470,16 +475,23 @@ static void gtk_graph_display_adjust_scroll_value(GtkGraphDisplay *display, GtkA static gboolean gtk_graph_display_draw(GtkWidget *widget, cairo_t *cr, GtkGraphDisplay *display) { + GtkDisplayPanel *parent; /* Autre version du composant */ cairo_surface_t *pat_image; /* Fond du futur pinceau */ cairo_t *pat_cr; /* Pinceau pour le pinceau */ cairo_pattern_t *pattern; /* Patron de remplissage */ double degrees; /* Conversion en degrés */ size_t i; /* Boucle de parcours */ + parent = GTK_DISPLAY_PANEL(display); + /* Eventuel fond pour la zone de compression */ if (display->may_collapsing && !GTK_DISPLAY_PANEL(display)->export) { + cairo_save(cr); + + cairo_scale(cr, parent->scale, parent->scale); + /* Préparation du pinceau */ pat_image = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, @@ -555,13 +567,21 @@ static gboolean gtk_graph_display_draw(GtkWidget *widget, cairo_t *cr, GtkGraphD cairo_surface_destroy(pat_image); + cairo_restore(cr); + } /* Dessin des ombres */ + cairo_save(cr); + + cairo_scale(cr, parent->scale, parent->scale); + void draw_shadow(GtkWidget *child, gpointer unused) { + GGraphCluster *cluster; /* Cluster correspondant */ GtkAllocation alloc; /* Emplacement de l'enfant */ + GtkAllocation area; /* Emplacement à considérer */ gint j; /* Boucle de parcours */ cairo_pattern_t *pattern; /* Zones d'application */ @@ -569,19 +589,30 @@ static gboolean gtk_graph_display_draw(GtkWidget *widget, cairo_t *cr, GtkGraphD if (!GTK_IS_DISPLAY_PANEL(child)) return; - gtk_widget_get_allocation(child, &alloc); + cluster = g_graph_cluster_find_by_widget(display->cluster, child); + assert(cluster != NULL); + + g_graph_cluster_get_allocation(cluster, &alloc); + + alloc.x += GRAPH_MARGIN; + alloc.y += GRAPH_MARGIN; + + area = alloc; for (j = 1; j < SHADOW_SIZE; j++) { cairo_push_group(cr); - gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x + j, alloc.y + j); + area.x = alloc.x + j; + area.y = alloc.y + j; + + gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, &area); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0); cairo_fill(cr); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, alloc.x, alloc.y); + gtk_display_panel_define_border_path(GTK_DISPLAY_PANEL(child), cr, &alloc); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); cairo_fill(cr); @@ -602,6 +633,8 @@ static gboolean gtk_graph_display_draw(GtkWidget *widget, cairo_t *cr, GtkGraphD for (i = 0; i < display->edges_count; i++) g_graph_edge_draw(display->edges[i], cr, true, display->hl_edge_index == i); + cairo_restore(cr); + return FALSE; } @@ -710,6 +743,7 @@ static gboolean gtk_graph_display_motion_notify(GtkWidget *widget, GdkEventMotio GtkAdjustment *hadj; /* Gestionnaire du défilement */ GtkAdjustment *vadj; /* Gestionnaire du défilement */ gdouble value; /* Nouvelle valeur bornée */ + double scale; /* Echelle appliquée au rendu */ size_t i; /* Boucle de parcours */ /* Déplacement du graphique ? */ @@ -739,8 +773,10 @@ static gboolean gtk_graph_display_motion_notify(GtkWidget *widget, GdkEventMotio /* Survol d'un lien ? */ else { + scale = GTK_DISPLAY_PANEL(display)->scale; + for (i = 0; i < display->edges_count; i++) - if (g_graph_edge_detect_at(display->edges[i], event->x, event->y)) + if (g_graph_edge_detect_at(display->edges[i], event->x / scale, event->y / scale)) { display->hl_edge_index = i; break; @@ -1131,21 +1167,28 @@ static GLineCursor *gtk_graph_display_get_cursor(const GtkGraphDisplay *display) static void gtk_graph_display_cache_glance(GtkGraphDisplay *display, cairo_t *cr, const GtkAllocation *area, double scale) { + GtkDisplayPanel *parent; /* Autre version du composant */ size_t i; /* Boucle de parcours */ + parent = GTK_DISPLAY_PANEL(display); + + cairo_scale(cr, scale * parent->scale, scale * parent->scale); + void draw_child_glance(GtkWidget *child, gpointer unused) { + GGraphCluster *cluster; /* Cluster correspondant */ GtkAllocation sub_area; /* Emplacement réservé */ if (!GTK_IS_BUFFER_DISPLAY(child)) return; - gtk_widget_get_allocation(child, &sub_area); + cluster = g_graph_cluster_find_by_widget(display->cluster, child); + assert(cluster != NULL); - sub_area.x *= scale; - sub_area.y *= scale; - sub_area.width = sub_area.width * scale + 1; - sub_area.height = sub_area.height * scale + 1; + g_graph_cluster_get_allocation(cluster, &sub_area); + + sub_area.x += GRAPH_MARGIN; + sub_area.y += GRAPH_MARGIN; g_loaded_panel_cache_glance(G_LOADED_PANEL(child), cr, &sub_area, scale); @@ -1153,8 +1196,6 @@ static void gtk_graph_display_cache_glance(GtkGraphDisplay *display, cairo_t *cr gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)draw_child_glance, NULL); - cairo_scale(cr, scale, scale); - for (i = 0; i < display->edges_count; i++) g_graph_edge_draw(display->edges[i], cr, false, false); @@ -1164,6 +1205,68 @@ static void gtk_graph_display_cache_glance(GtkGraphDisplay *display, cairo_t *cr /****************************************************************************** * * * Paramètres : display = composant GTK à mettre à jour. * +* old = ancienne échelle appliquée. * +* new = nouvelle échelle à appliquer. * +* * +* Description : Spécifie l'échelle à appliquer à l'affichage du composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_graph_display_apply_scale(GtkGraphDisplay *display, double old, double new) +{ + GtkDisplayPanel *parent; /* Autre version du composant */ + gint right; /* Abscisse du coin droit */ + gint bottom; /* Ordonnée du coin inférieur */ + + /* Traitement des blocs */ + + void apply_child_scale(GtkWidget *child, gpointer unused) + { + GGraphCluster *cluster; /* Cluster correspondant */ + GtkAllocation sub_area; /* Emplacement réservé */ + gint x; /* Abscisse du point d'arrivée */ + gint y; /* Ordonnée du point d'arrivée */ + + if (!GTK_IS_BUFFER_DISPLAY(child)) + return; + + cluster = g_graph_cluster_find_by_widget(display->cluster, child); + assert(cluster != NULL); + + g_graph_cluster_get_allocation(cluster, &sub_area); + + x = (GRAPH_MARGIN + sub_area.x) * new; + y = (GRAPH_MARGIN + sub_area.y) * new; + + gtk_fixed_move(GTK_FIXED(display->support), child, x, y); + + gtk_display_panel_set_scale(GTK_DISPLAY_PANEL(child), new); + + } + + gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)apply_child_scale, NULL); + + /* Calcul du nouvel espace nécessaire */ + + parent = GTK_DISPLAY_PANEL(display); + + gtk_graph_display_compute_requested_size(display, &right, &bottom); + + right *= parent->scale; + bottom *= parent->scale; + + gtk_fixed_move(GTK_FIXED(display->support), display->extender, right - 1, bottom - 1); + +} + + +/****************************************************************************** +* * +* Paramètres : display = composant GTK à mettre à jour. * * export = préparation d'une exportation complète du rendu ? * * * * Description : Marque ou non le composant pour une exportation prochaine. * @@ -1238,8 +1341,7 @@ GtkWidget *gtk_graph_display_get_support(GtkGraphDisplay *display) * * * Paramètres : display = composant GTK à mettre à jour. * * widget = composant GTK à insérer. * -* x = abscisse du point d'insertion. * -* y = ordonnée du point d'insertion. * +* alloc = position du point d'insertion. * * * * Description : Place une vue sous forme de bloc dans le graphique. * * * @@ -1261,7 +1363,6 @@ void gtk_graph_display_put(GtkGraphDisplay *display, GtkWidget *widget, const Gt } - /****************************************************************************** * * * Paramètres : display = composant GTK à mettre à jour. * diff --git a/src/gui/menus/menubar.c b/src/gui/menus/menubar.c index aa89a13..d386362 100644 --- a/src/gui/menus/menubar.c +++ b/src/gui/menus/menubar.c @@ -309,7 +309,7 @@ static void change_menubar_current_view(GMenuBar *bar, GLoadedPanel *old, GLoade rebuild_menu_view_for_view(bar->view, new); - update_access_for_view_in_menu_view(G_EDITOR_ITEM(bar)->ref, new); + update_access_for_view_in_menu_view(new); update_access_for_view_in_menu_binary(new); diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c index 255f1d9..018cfbf 100644 --- a/src/gui/menus/view.c +++ b/src/gui/menus/view.c @@ -40,6 +40,7 @@ #include "../core/panels.h" #include "../../analysis/loaded.h" #include "../../gtkext/easygtk.h" +#include "../../gtkext/gtkdisplaypanel.h" #include "../../gtkext/gtkgraphdisplay.h" @@ -65,6 +66,9 @@ static void handle_loaded_panel_first_allocation(GtkWidget *, GdkRectangle *, GL /* Effectue la bascule d'un panneau de chargement à un autre. */ static void change_current_view_support(unsigned int); +/* Réagit avec le menu "Affichage -> Zoom *". */ +static void mcb_view_zoom(GtkCheckMenuItem *, gpointer ); + /* Réagit avec le menu "Affichage -> (colonne xxx)". */ static void mcb_view_display_column(GtkCheckMenuItem *, gpointer); @@ -126,6 +130,28 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar) /* Séparation */ submenuitem = qck_create_menu_separator(); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + /* Zooms */ + + submenuitem = qck_create_menu_item(ref, "mnu_view_zoom_in", _("Zoom in"), + G_CALLBACK(mcb_view_zoom), GINT_TO_POINTER(0)); + add_accelerator_to_widget(submenuitem, "plus"); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenuitem = qck_create_menu_item(ref, "mnu_view_zoom_out", _("Zoom out"), + G_CALLBACK(mcb_view_zoom), GINT_TO_POINTER(1)); + add_accelerator_to_widget(submenuitem, "minus"); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + submenuitem = qck_create_menu_item(ref, "mnu_view_zoom_reset", _("Reset zoom"), + G_CALLBACK(mcb_view_zoom), GINT_TO_POINTER(2)); + add_accelerator_to_widget(submenuitem, "0"); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + /* Séparation */ + + submenuitem = qck_create_menu_separator(); g_object_set_data(ref, "mnu_view_start_options", submenuitem); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); @@ -399,8 +425,7 @@ void rebuild_menu_view_for_view(GtkWidget *widget, GLoadedPanel *new) /****************************************************************************** * * -* Paramètres : ref = espace de référencements à consulter. * -* panel = panneau d'affichage actif ou NULL si aucun. * +* Paramètres : new = nouvelle vue du contenu chargé analysé. * * * * Description : Met à jour les accès du menu "Affichage" selon le contenu. * * * @@ -410,12 +435,31 @@ void rebuild_menu_view_for_view(GtkWidget *widget, GLoadedPanel *new) * * ******************************************************************************/ -void update_access_for_view_in_menu_view(GObject *ref, GLoadedPanel *panel) +void update_access_for_view_in_menu_view(GLoadedPanel *new) { + GObject *ref; /* Espace de référencements */ + gboolean access; /* Accès à déterminer */ + GtkWidget *item; /* Elément de menu à traiter */ + + ref = get_global_ref(); + /* Bascules */ update_switch_access_in_menu_view(); + /* Zooms */ + + access = GTK_IS_GRAPH_DISPLAY(new); + + item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_zoom_in")); + gtk_widget_set_sensitive(item, access); + + item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_zoom_out")); + gtk_widget_set_sensitive(item, access); + + item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_zoom_reset")); + gtk_widget_set_sensitive(item, access); + } @@ -843,6 +887,49 @@ static void change_current_view_support(unsigned int wanted) /****************************************************************************** * * +* Paramètres : menuitem = élément de menu sélectionné. * +* data = données indiquant la nature du zoom. * +* * +* Description : Réagit avec le menu "Affichage -> Zoom *". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_view_zoom(GtkCheckMenuItem *menuitem, gpointer data) +{ + GtkDisplayPanel *panel; /* Afficheur effectif de code */ + double scale; /* Echelle à appliquer */ + + panel = GTK_DISPLAY_PANEL(get_current_view()); + + scale = gtk_display_panel_get_scale(panel); + + switch (GPOINTER_TO_INT(data)) + { + case 0: + scale /= 1.25; + break; + + case 1: + scale *= 1.25; + break; + + case 2: + scale = 1.0; + break; + + } + + gtk_display_panel_set_scale(panel, scale); + +} + + +/****************************************************************************** +* * * Paramètres : menuitem = élément de menu ayant basculé. * * unused = adresse non utilisée ici. * * * diff --git a/src/gui/menus/view.h b/src/gui/menus/view.h index 2271d4c..d3d70ab 100644 --- a/src/gui/menus/view.h +++ b/src/gui/menus/view.h @@ -44,7 +44,7 @@ void rebuild_menu_view_for_content(GtkWidget *, GLoadedContent *); void rebuild_menu_view_for_view(GtkWidget *, GLoadedPanel *); /* Met à jour les accès du menu "Affichage" selon le contenu. */ -void update_access_for_view_in_menu_view(GObject *, GLoadedPanel *); +void update_access_for_view_in_menu_view(GLoadedPanel *); /* Réagit avec le menu "Affichage -> Panneaux latéraux". */ void mcb_view_update_side_panels_list(GtkMenuItem *, GMenuBar *); -- cgit v0.11.2-87-g4458