summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gtkext/graph/cluster.c3
-rw-r--r--src/gtkext/graph/edge.c135
-rw-r--r--src/gtkext/graph/edge.h9
-rw-r--r--src/gtkext/gtkgraphdisplay.c44
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;
}