From 549dd203344a2f95f4bc596f963a854af004cba2 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sun, 28 Jun 2009 21:22:52 +0000 Subject: Drawn graphic links between the different blocks of code. git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@81 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a --- ChangeLog | 28 +++++++++++ src/graph/dot.c | 90 +++++++++++++++++++++++++++++++++- src/graph/dot.h | 4 ++ src/graph/layout.c | 29 +++++++++-- src/graph/layout.h | 4 +- src/graph/node.c | 67 ++++++++++++++++++++++++-- src/gtkext/Makefile.am | 1 + src/gtkext/gtkblockview.c | 24 +++++++--- src/gtkext/gtkgraphview.c | 120 +++++++++++++++++++++++++++++++++++++++++++++- src/gtkext/gtkgraphview.h | 6 +++ 10 files changed, 353 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index acd0420..7d2186d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +09-06-28 Cyrille Bagard + + * src/graph/dot.c: + * src/graph/dot.h: + Fix a mistake about the coordinates origin. + Load links from the dot's output. + + * src/graph/layout.c: + * src/graph/layout.h: + Load and attach graphic links. + + * src/graph/node.c: + Use the dpi value to place code blocks. + + * src/gtkext/gtkblockview.c: + Typo. + + * src/gtkext/gtkgraphview.c: + * src/gtkext/gtkgraphview.h: + Draw graphic links between the different blocks of code. + + * src/gtkext/gtklinkrenderer.c: + * src/gtkext/gtklinkrenderer.h: + New entries: support graphic links between the different blocks of code. + + * src/gtkext/Makefile.am: + Add gtklinkrenderer.[ch] to libgtkext_la_SOURCES. + 09-06-25 Cyrille Bagard * configure.ac: diff --git a/src/graph/dot.c b/src/graph/dot.c index dc1c9a9..e4ee38c 100644 --- a/src/graph/dot.c +++ b/src/graph/dot.c @@ -71,16 +71,26 @@ graph_layout *create_graph_layout(char *cmds) printf("ret = %d\n", ret); - + /* + ret = gvLayoutJobs(result->context, result->graph); + printf("ret = %d\n", ret); + ret = gvRenderJobs(result->context, result->graph); + printf("ret = %d\n", ret); + */ ret = gvRender(result->context, result->graph, "dot", NULL); + + + ret = gvRender(result->context, result->graph, "plain", NULL); + printf("ret = %d\n", ret); + return result; cdl_error: @@ -136,13 +146,89 @@ void delete_graph_layout(graph_layout *layout) void place_nodes_of_graph_layout(const graph_layout *layout, GtkFixed *fixed, GGraphNode **nodes, size_t count) { + int height; /* Hauteur du graphique */ node_t *iter; /* Boucle de parcours */ GGraphNode *node; /* Intermédiaire concerné */ + height = GD_bb(layout->graph).UR.y; + for (iter = agfstnode(layout->graph); iter != NULL; iter = agnxtnode(layout->graph, iter)) { + + printf(" pos :: (%d ; %d)\n", iter->u.coord.x, height - iter->u.coord.y); + node = find_graph_node_by_name(nodes, count, iter->name); - g_graph_node_place(node, fixed, (double)iter->u.coord.x, (double)iter->u.coord.y); + g_graph_node_place(node, fixed, iter->u.coord.x, height - iter->u.coord.y); } } + + +/****************************************************************************** +* * +* Paramètres : layout = graphique à supprimer de la mémoire. * +* count = nombre d'éléments mis en place. * +* * +* Description : Charge la définition de tous les liens graphiques. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkLinkRenderer **create_links_from_graph_layout(const graph_layout *layout, size_t *count) +{ + GtkLinkRenderer **result; /* Liste à retourner */ + int height; /* Hauteur du graphique */ + node_t *niter; /* Boucle de parcours #1 */ + edge_t *eiter; /* Boucle de parcours #2 */ + splines *lines; /* Lignes déjà tracées */ + int i; /* Boucle de parcours #3 */ + int k; /* Boucle de parcours #4 */ + GdkPoint *points; /* Points de ligne relus */ + size_t points_count; /* Nombre de ces points */ + + result = NULL; + *count = 0; + + height = GD_bb(layout->graph).UR.y; + + for (niter = agfstnode(layout->graph); niter != NULL; niter = agnxtnode(layout->graph, niter)) + for (eiter = agfstout(layout->graph, niter); eiter != NULL; eiter = agnxtout(layout->graph, eiter)) + { + lines = ED_spl(eiter); + + printf("edge == %p\n", eiter); + + points = NULL; + points_count = 0; + + for (i = 0; i < lines->size; i++) + { + points = (GdkPoint *)realloc(points, (points_count + lines->list[i].size) * sizeof(GdkPoint)); + + for (k = 0; k < lines->list[i].size; k++) + { + points[points_count + k].x = lines->list[i].list[k].x; + points[points_count + k].y = height - lines->list[i].list[k].y; + + printf(" ... ( %d ; %d)\n", + lines->list[i].list[k].x, height - lines->list[i].list[k].y); + + } + + points_count += lines->list[i].size; + + printf(" ...\n"); + + } + + result = (GtkLinkRenderer **)realloc(result, ++(*count) * sizeof(GtkLinkRenderer *)); + result[*count - 1] = gtk_link_renderer_new(points, points_count); + + } + + return result; + +} diff --git a/src/graph/dot.h b/src/graph/dot.h index 8538e52..630c1cb 100644 --- a/src/graph/dot.h +++ b/src/graph/dot.h @@ -26,6 +26,7 @@ #include "node.h" +#include "../gtkext/gtklinkrenderer.h" @@ -42,6 +43,9 @@ void delete_graph_layout(graph_layout *); /* Place tous les éléments du graphique à l'écran. */ void place_nodes_of_graph_layout(const graph_layout *, GtkFixed *, GGraphNode **, size_t); +/* Charge la définition de tous les liens graphiques. */ +GtkLinkRenderer **create_links_from_graph_layout(const graph_layout *, size_t *); + #endif /* _GRAPH_DOT_H */ diff --git a/src/graph/layout.c b/src/graph/layout.c index c76df49..faf439b 100644 --- a/src/graph/layout.c +++ b/src/graph/layout.c @@ -26,6 +26,7 @@ #include #include +#include #include "dot.h" @@ -36,7 +37,7 @@ /****************************************************************************** * * -* Paramètres : fixed = support à placer les différents éléments. * +* Paramètres : view = support à placer les différents éléments. * * views = morceaux de code à afficher de façon organisée. * * count = quantité de ces morceaux de code. * * * @@ -48,12 +49,14 @@ * * ******************************************************************************/ -bool build_graph_view(GtkFixed *fixed, GtkBinView **views, size_t count) +bool build_graph_view(GtkGraphView *view, GtkBinView **views, size_t count) { GGraphNode **nodes; /* Intermédiaires en place */ size_t i; /* Boucle de parcours */ char *cmds; /* Description à envoyer à dot */ graph_layout *layout; /* Graphique construit */ + GtkLinkRenderer **links; /* Liens graphiques construits */ + size_t links_count; /* Quantité de ces liens */ /* Création de la glue */ @@ -64,7 +67,8 @@ bool build_graph_view(GtkFixed *fixed, GtkBinView **views, size_t count) /* Définition du graphique */ - cmds = strdup("digraph G {\n"); + cmds = strdup("digraph G {\noverlap=false;\n splines=true;\n"); + //cmds = strdup("digraph G {\n"); for (i = 0; i < count; i++) cmds = g_graph_node_register_for_dot(nodes[i], cmds); @@ -72,6 +76,20 @@ bool build_graph_view(GtkFixed *fixed, GtkBinView **views, size_t count) + + + + for (i = 0; (i + 1) < count; i++) + { + char buffer[128]; + snprintf(buffer, 128, "_%p -> _%p;\n", views[i], views[i + 1]); + cmds = stradd(cmds, buffer); + } + + + + + cmds = stradd(cmds, "}"); printf("first step :: '%s'\n", cmds); @@ -80,9 +98,10 @@ bool build_graph_view(GtkFixed *fixed, GtkBinView **views, size_t count) /* Affichage du graphique */ - place_nodes_of_graph_layout(layout, fixed, nodes, count); - + place_nodes_of_graph_layout(layout, GTK_FIXED(view), nodes, count); + links = create_links_from_graph_layout(layout, &links_count); + gtk_graph_view_attach_links(view, links, links_count); delete_graph_layout(layout); diff --git a/src/graph/layout.h b/src/graph/layout.h index cbb8e6c..5212168 100644 --- a/src/graph/layout.h +++ b/src/graph/layout.h @@ -26,15 +26,15 @@ #include -#include #include "../gtkext/gtkbinview.h" +#include "../gtkext/gtkgraphview.h" /* Dispose une série de morceaux d'affichage en graphique. */ -bool build_graph_view(GtkFixed *, GtkBinView **, size_t); +bool build_graph_view(GtkGraphView *, GtkBinView **, size_t); diff --git a/src/graph/node.c b/src/graph/node.c index b220c4f..8432476 100644 --- a/src/graph/node.c +++ b/src/graph/node.c @@ -50,6 +50,9 @@ struct _GGraphNodeClass { GObjectClass parent; /* A laisser en premier */ + double dpi_x; /* Résolution en abscisse */ + double dpi_y; /* Résolution en ordonnée */ + }; @@ -84,6 +87,44 @@ G_DEFINE_TYPE(GGraphNode, g_graph_node, G_TYPE_OBJECT); static void g_graph_node_class_init(GGraphNodeClass *klass) { + GdkScreen *screen; /* Ecran par défaut */ + gint width; /* Largeur d'écran en pixels */ + gint height; /* Hauteur d'écran en pixels */ + gint width_mm; /* Largeur d'écran en mm. */ + gint height_mm; /* Hauteur d'écran en mm. */ + + screen = gdk_screen_get_default(); + + width = gdk_screen_get_width(screen); + height = gdk_screen_get_height(screen); + + width_mm = gdk_screen_get_width_mm(screen); + height_mm = gdk_screen_get_height_mm(screen); + + /** + * Il y a 2.54 centimètres, soit 25.4 millimètres, dans un pouce. + * On a donc : + * + * dpi = N pixels / (M millimètres / (25.4 millimètres / 1 pouce)) + * = N pixels / (M pouces / 25.4) + * = N * 25.4 pixels / M pouces + * + */ + + if (width_mm > 0 && height_mm > 0) + { + klass->dpi_x = (width * 25.4) / (double)width_mm; + klass->dpi_y = (height * 25.4) / (double)height_mm; + } + else + { + klass->dpi_x = 96; + klass->dpi_y = 96; + } + + + klass->dpi_x = 72; + klass->dpi_y = 72; } @@ -136,7 +177,7 @@ GGraphNode *g_graph_node_new(GtkBinView *view) } - +#include /****************************************************************************** * * * Paramètres : node = intermédiaire à consulter. * @@ -153,14 +194,27 @@ GGraphNode *g_graph_node_new(GtkBinView *view) char *g_graph_node_register_for_dot(const GGraphNode *node, char *cmds) { GtkRequisition requisition; /* Taille à l'écran requise */ + char buffer[128]; + + gtk_widget_size_request(GTK_WIDGET(node->view), &requisition); cmds = stradd(cmds, node->name); + cmds = stradd(cmds, " [shape=box, fixedsize "); - gtk_widget_size_request(GTK_WIDGET(node->view), &requisition); + printf(" req=(%d ; %d) -->> (%g ; %g)\n", + requisition.width, + requisition.height, + requisition.width / G_GRAPH_NODE_GET_CLASS(node)->dpi_x, + requisition.height / G_GRAPH_NODE_GET_CLASS(node)->dpi_y); + snprintf(buffer, 128, ", width=\"%g\"", round(requisition.width / G_GRAPH_NODE_GET_CLASS(node)->dpi_x) + 1.0); + cmds = stradd(cmds, buffer); - cmds = stradd(cmds, " [shape=box];\n"); + snprintf(buffer, 128, ", height=\"%g\"", round(requisition.height / G_GRAPH_NODE_GET_CLASS(node)->dpi_y) + 1.0); + cmds = stradd(cmds, buffer); + + cmds = stradd(cmds, "];\n"); return cmds; @@ -184,6 +238,13 @@ char *g_graph_node_register_for_dot(const GGraphNode *node, char *cmds) void g_graph_node_place(const GGraphNode *node, GtkFixed *fixed, gint x, gint y) { + GtkRequisition requisition; /* Taille à l'écran actuelle */ + + gtk_widget_size_request(GTK_WIDGET(node->view), &requisition); + + x -= requisition.width / 2; + y -= requisition.height / 2; + gtk_fixed_put(fixed, GTK_WIDGET(node->view), x, y); } diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am index a7023c5..51bea0f 100644 --- a/src/gtkext/Makefile.am +++ b/src/gtkext/Makefile.am @@ -12,6 +12,7 @@ libgtkext_la_SOURCES = \ gtkdockpanel.h gtkdockpanel.c \ gtkdropwindow.h gtkdropwindow.c \ gtkgraphview.h gtkgraphview.c \ + gtklinkrenderer.h gtklinkrenderer.c \ iodamarshal.h iodamarshal.c \ support.h support.c diff --git a/src/gtkext/gtkblockview.c b/src/gtkext/gtkblockview.c index 648421d..10941ab 100644 --- a/src/gtkext/gtkblockview.c +++ b/src/gtkext/gtkblockview.c @@ -103,8 +103,8 @@ static void gtk_block_view_realize(GtkWidget *widget); static gboolean gtk_block_view_button_press(GtkWidget *, GdkEventButton *event); -static gboolean gtk_block_view_expose(GtkWidget *widget, - GdkEventExpose *event); +/* Met à jour l'affichage de la vue sous forme de bloc. */ +static gboolean gtk_block_view_expose(GtkWidget *widget, GdkEventExpose *event); static void gtk_block_view_paint(GtkBlockView *view); static void gtk_block_view_destroy(GtkObject *object); @@ -129,7 +129,7 @@ GtkWidget * gtk_block_view_new(void) static void gtk_block_view_class_init(GtkBlockViewClass *klass) { - GtkWidgetClass *widget_class; + GtkWidgetClass *widget_class; /* Classe version Widget */ GtkObjectClass *object_class; @@ -313,9 +313,21 @@ void gtk_block_view_update_margin(GRenderingLine *line, GtkBlockView *view) -static gboolean -gtk_block_view_expose(GtkWidget *widget, - GdkEventExpose *event) + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à redessiner. * +* event = informations liées à l'événement. * +* * +* Description : Met à jour l'affichage de la vue sous forme de bloc. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_block_view_expose(GtkWidget *widget, GdkEventExpose *event) { g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(GTK_IS_BLOCK_VIEW(widget), FALSE); diff --git a/src/gtkext/gtkgraphview.c b/src/gtkext/gtkgraphview.c index 8389148..8a25940 100644 --- a/src/gtkext/gtkgraphview.c +++ b/src/gtkext/gtkgraphview.c @@ -37,12 +37,17 @@ struct _GtkGraphView { GtkBinView parent; /* A laisser en premier */ + GdkGC *gc; /* Contexte graphique du rendu */ + vmpa_t start; /* Début de la portion vue */ vmpa_t end; /* Fin de la portion affichée */ GtkBinView **childs; /* Liste des sous-blocs */ size_t childs_count; /* Taille de cette liste */ + GtkLinkRenderer **links; /* Liste des liens graphiques */ + size_t links_count; /* Nombre de ces liens */ + }; /* Représentation de code binaire sous forme graphique (classe) */ @@ -59,6 +64,11 @@ static void gtk_graph_view_class_init(GtkGraphViewClass *); /* Initialise une instance d'afficheur de code en graphique. */ static void gtk_graph_view_init(GtkGraphView *); +static void gtk_graph_view_realize(GtkWidget *widget); + +/* Met à jour l'affichage de la vue sous forme graphique. */ +static gboolean gtk_graph_view_expose(GtkGraphView *, GdkEventExpose *); + /* Supprime tout contenu de l'afficheur de code en graphique. */ static void gtk_graph_view_reset(GtkGraphView *); @@ -81,7 +91,7 @@ G_DEFINE_TYPE(GtkGraphView, gtk_graph_view, GTK_TYPE_BIN_VIEW) /****************************************************************************** * * -* Paramètres : class = classe GTK à initialiser. * +* Paramètres : klass = classe GTK à initialiser. * * * * Description : Initialise la classe générique des graphiques de code. * * * @@ -91,8 +101,14 @@ G_DEFINE_TYPE(GtkGraphView, gtk_graph_view, GTK_TYPE_BIN_VIEW) * * ******************************************************************************/ -static void gtk_graph_view_class_init(GtkGraphViewClass *class) +static void gtk_graph_view_class_init(GtkGraphViewClass *klass) { + GtkWidgetClass *widget_class; /* Classe version Widget */ + + widget_class = (GtkWidgetClass *)klass; + + widget_class->realize = gtk_graph_view_realize; + widget_class->expose_event = gtk_graph_view_expose; } @@ -141,6 +157,82 @@ GtkWidget* gtk_graph_view_new(void) } + + + + + + + +static void +gtk_graph_view_realize(GtkWidget *widget) +{ + GdkWindowAttr attributes; + guint attributes_mask; + GdkColor white; /* Couleur de fond normale */ + + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_GRAPH_VIEW(widget)); + + GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.event_mask = gtk_widget_get_events(widget) | GDK_BUTTON_PRESS_MASK | GDK_EXPOSURE_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + widget->window = gdk_window_new( + gtk_widget_get_parent_window (widget), + & attributes, attributes_mask + ); + + gdk_window_set_user_data(widget->window, widget); + + widget->style = gtk_style_attach(widget->style, widget->window); + + + gdk_color_white(gtk_widget_get_colormap(widget), &white); + gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &white); + + + GTK_GRAPH_VIEW(widget)->gc = gdk_gc_new(GDK_DRAWABLE(widget->window)); + +} + + + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à redessiner. * +* event = informations liées à l'événement. * +* * +* Description : Met à jour l'affichage de la vue sous forme graphique. * +* * +* Retour : FALSE pour poursuivre la propagation de l'événement. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gboolean gtk_graph_view_expose(GtkGraphView *view, GdkEventExpose *event) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < view->links_count; i++) + gtk_link_renderer_draw(view->links[i], GDK_DRAWABLE(GTK_WIDGET(view)->window), view->gc); + + return FALSE; + +} + + /****************************************************************************** * * * Paramètres : view = instance GTK à réinitialiser. * @@ -404,3 +496,27 @@ static GtkBinView **gtk_graph_view_load_nodes(openida_binary *binary, GRendering } + + +/****************************************************************************** +* * +* Paramètres : view = composant GTK à mettre à jour. * +* links = liens graphiques entre les blocs à intégrer. * +* count = quantité de ces liens graphiques. * +* * +* Description : Définit les liens graphiques à présenter avec la vue. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_graph_view_attach_links(GtkGraphView *view, GtkLinkRenderer **links, size_t count) +{ + /* TODO : free ? */ + + view->links = links; + view->links_count = count; + +} diff --git a/src/gtkext/gtkgraphview.h b/src/gtkext/gtkgraphview.h index 12dd606..1d0c2ab 100644 --- a/src/gtkext/gtkgraphview.h +++ b/src/gtkext/gtkgraphview.h @@ -28,6 +28,9 @@ #include +#include "gtklinkrenderer.h" + + #define GTK_TYPE_GRAPH_VIEW (gtk_graph_view_get_type()) #define GTK_GRAPH_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_GRAPH_VIEW, GtkGraphView)) @@ -51,6 +54,9 @@ GType gtk_graph_view_get_type(void); /* Crée un nouveau composant pour l'affichage en graphique. */ GtkWidget* gtk_graph_view_new(void); +/* Définit les liens graphiques à présenter avec la vue. */ +void gtk_graph_view_attach_links(GtkGraphView *, GtkLinkRenderer **, size_t); + #endif /* _GTKEXT_GTKGRAPHVIEW_H */ -- cgit v0.11.2-87-g4458