From 5ed40f0afbd58fbfdf05be7b2a10ab8d0819759f Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 14 Feb 2019 12:28:45 +0100 Subject: Highlighted graph view edges. --- src/gtkext/graph/cluster.c | 3 - src/gtkext/graph/edge.c | 135 +++++++++++++++++++++++++++++++++++-------- src/gtkext/graph/edge.h | 9 ++- src/gtkext/gtkgraphdisplay.c | 44 ++++++++++++-- 4 files changed, 158 insertions(+), 33 deletions(-) diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c index 12f88bd..c4deeaa 100644 --- a/src/gtkext/graph/cluster.c +++ b/src/gtkext/graph/cluster.c @@ -279,9 +279,6 @@ struct _GGraphClusterClass /* Espace minimal vertical entre les blocs */ #define VERTICAL_MARGIN 15 -/* Espace minimal entre les liens */ -#define LINK_MARGIN 10 - /* Initialise la classe des mises en disposition graphique. */ static void g_graph_cluster_class_init(GGraphClusterClass *); diff --git a/src/gtkext/graph/edge.c b/src/gtkext/graph/edge.c index e3844f3..9a2f848 100644 --- a/src/gtkext/graph/edge.c +++ b/src/gtkext/graph/edge.c @@ -285,42 +285,131 @@ void g_graph_edge_offset(GGraphEdge *edge, gint dx, gint dy) /****************************************************************************** * * -* Paramètres : edge = ligne de rendu à manipuler. * -* cairo = assistant pour le rendu graphique. * -* arrow = indique le besoin en flèche à l'arrivée. * +* Paramètres : edge = ligne de rendu avec positions à consulter. * +* x = emplacement de la souris sur l'axe des abscisses. * +* y = emplacement de la souris sur l'axe des ordonnées. * * * -* Description : Dessine les liens graphiques enregistrés dans le moteur. * +* Description : Opère un décalage du lien dans une direction donnée. * * * -* Retour : - * +* Retour : true si un survol est en cours, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -void g_graph_edge_draw(const GGraphEdge *edge, cairo_t *cairo, bool arrow) +bool g_graph_edge_detect_at(const GGraphEdge *edge, gint x, gint y) { + bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ + gint margin; /* Marge de précision */ + gint pts[2]; /* Points d'analyse ordonnés */ + gint inter[2]; /* Bilan d'intersection */ - switch (edge->color) + result = false; + + for (i = 1; i < edge->count; i++) { - default: - case EGC_DEFAULT: - cairo_set_source_rgb(cairo, 0, 0, 0); - break; - case EGC_GREEN: - cairo_set_source_rgb(cairo, 0, 0.6, 0); - break; - case EGC_RED: - cairo_set_source_rgb(cairo, 0.8, 0, 0); - break; - case EGC_BLUE: - cairo_set_source_rgb(cairo, 0, 0, 0.8); - break; - case EGC_DASHED_GRAY: - cairo_set_source_rgb(cairo, 0.4, 0.4, 0.4); - break; + /* Au niveau des abscisses */ + + if (edge->points[i - 1].x <= edge->points[i].x) + { + pts[0] = edge->points[i - 1].x; + pts[1] = edge->points[i].x; + margin = 1; + } + else + { + pts[0] = edge->points[i].x; + pts[1] = edge->points[i - 1].x; + margin = 1; + } + + margin *= (LINK_MARGIN / 2); + + inter[0] = MAX(pts[0] - margin, x); + inter[1] = MIN(pts[1] + margin, x); + + if (inter[0] > inter[1]) + continue; + + /* Au niveau des ordonnées */ + + if (edge->points[i - 1].y <= edge->points[i].y) + { + pts[0] = edge->points[i - 1].y; + pts[1] = edge->points[i].y; + margin = 1; + } + else + { + pts[0] = edge->points[i].y; + pts[1] = edge->points[i - 1].y; + margin = 1; + } + + margin *= (LINK_MARGIN / 2); + + inter[0] = MAX(pts[0] - margin, y); + inter[1] = MIN(pts[1] + margin, y); + + if (inter[0] > inter[1]) + continue; + + /* Détection ! */ + + result = true; + break; + } + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : edge = ligne de rendu à manipuler. * +* cairo = assistant pour le rendu graphique. * +* arrow = indique le besoin en flèche à l'arrivée. * +* selected = s'agit-il d'un lien sélectionné ? * +* * +* Description : Dessine les liens graphiques enregistrés dans le moteur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_graph_edge_draw(const GGraphEdge *edge, cairo_t *cairo, bool arrow, bool selected) +{ + size_t i; /* Boucle de parcours */ + + if (selected) + cairo_set_source_rgb(cairo, 1.0, 1.0, 1.0); + + else + switch (edge->color) + { + default: + case EGC_DEFAULT: + cairo_set_source_rgb(cairo, 0, 0, 0); + break; + case EGC_GREEN: + cairo_set_source_rgb(cairo, 0, 0.6, 0); + break; + case EGC_RED: + cairo_set_source_rgb(cairo, 0.8, 0, 0); + break; + case EGC_BLUE: + cairo_set_source_rgb(cairo, 0, 0, 0.8); + break; + case EGC_DASHED_GRAY: + cairo_set_source_rgb(cairo, 0.4, 0.4, 0.4); + break; + } + switch (edge->color) { default: diff --git a/src/gtkext/graph/edge.h b/src/gtkext/graph/edge.h index 23fcf8d..e905685 100644 --- a/src/gtkext/graph/edge.h +++ b/src/gtkext/graph/edge.h @@ -60,6 +60,10 @@ typedef enum _EdgeColor } EdgeColor; +/* Espace minimal entre les liens */ +#define LINK_MARGIN 10 + + /* Indique le type défini par la GLib pour les liens graphiques entre noeuds. */ GType g_graph_edge_get_type(void); @@ -87,8 +91,11 @@ void g_graph_edge_resolve(GGraphEdge *); /* Opère un décalage du lien dans une direction donnée. */ void g_graph_edge_offset(GGraphEdge *, gint, gint); +/* Opère un décalage du lien dans une direction donnée. */ +bool g_graph_edge_detect_at(const GGraphEdge *, gint, gint); + /* Dessine les liens graphiques enregistrés dans le moteur. */ -void g_graph_edge_draw(const GGraphEdge *, cairo_t *, bool); +void g_graph_edge_draw(const GGraphEdge *, cairo_t *, bool, bool); diff --git a/src/gtkext/gtkgraphdisplay.c b/src/gtkext/gtkgraphdisplay.c index 51ca344..0915f3a 100644 --- a/src/gtkext/gtkgraphdisplay.c +++ b/src/gtkext/gtkgraphdisplay.c @@ -54,6 +54,7 @@ struct _GtkGraphDisplay GGraphEdge **edges; /* Liens entre les noeuds */ size_t edges_count; /* Quantité de ces liens */ + size_t hl_edge_index; /* Indice du lien survolé */ gdouble start_x; /* Abscisse du point de souris */ gdouble start_y; /* Ordonnée du point de souris */ @@ -214,7 +215,8 @@ static void gtk_graph_display_init(GtkGraphDisplay *display) G_CALLBACK(gtk_graph_display_motion_notify), display); gtk_widget_add_events(display->support, - GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); + GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + | GDK_POINTER_MOTION_MASK); gtk_widget_show(display->support); @@ -481,7 +483,7 @@ static gboolean gtk_graph_display_draw(GtkWidget *widget, cairo_t *cr, GtkGraphD gtk_container_foreach(GTK_CONTAINER(display->support), (GtkCallback)draw_shadow, NULL); for (i = 0; i < display->edges_count; i++) - g_graph_edge_draw(display->edges[i], cr, true); + g_graph_edge_draw(display->edges[i], cr, true, display->hl_edge_index == i); return FALSE; @@ -591,9 +593,14 @@ 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 */ + size_t i; /* Boucle de parcours */ - if (event->state & GDK_BUTTON1_MASK && display->big_enough) + /* Déplacement du graphique ? */ + if (event->state & GDK_BUTTON1_MASK) { + if (!display->big_enough) + goto done; + diff_x = display->start_x - event->x_root; diff_y = display->start_y - event->y_root; @@ -612,6 +619,29 @@ static gboolean gtk_graph_display_motion_notify(GtkWidget *widget, GdkEventMotio } + /* Survol d'un lien ? */ + else + { + for (i = 0; i < display->edges_count; i++) + if (g_graph_edge_detect_at(display->edges[i], event->x, event->y)) + { + display->hl_edge_index = i; + break; + } + + if (i < display->edges_count) + gtk_widget_queue_draw(widget); + + else if (display->hl_edge_index < display->edges_count) + { + display->hl_edge_index = display->edges_count; + gtk_widget_queue_draw(widget); + } + + } + + done: + return FALSE; } @@ -922,7 +952,7 @@ static void gtk_graph_display_cache_glance(GtkGraphDisplay *display, cairo_t *cr cairo_scale(cr, scale, scale); for (i = 0; i < display->edges_count; i++) - g_graph_edge_draw(display->edges[i], cr, false); + g_graph_edge_draw(display->edges[i], cr, false, false); } @@ -990,11 +1020,12 @@ void gtk_graph_display_add_edge(GtkGraphDisplay *display, GGraphEdge *edge) { g_graph_edge_offset(edge, GRAPH_MARGIN, GRAPH_MARGIN); - display->edges = (GGraphEdge **)realloc(display->edges, - ++display->edges_count * sizeof(GGraphEdge *)); + display->edges = realloc(display->edges, ++display->edges_count * sizeof(GGraphEdge *)); display->edges[display->edges_count - 1] = edge; + display->hl_edge_index = display->edges_count; + } @@ -1055,6 +1086,7 @@ static void gtk_graph_display_reset(GtkGraphDisplay *display, bool dispose) display->edges = NULL; display->edges_count = 0; + display->hl_edge_index = 0; } -- cgit v0.11.2-87-g4458