summaryrefslogtreecommitdiff
path: root/src/gtkext
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-02-15 22:58:40 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-02-15 22:58:40 (GMT)
commit16242be5838a77690946cbb2f30b2e89f2df0b94 (patch)
treed3c2b2725f41f2a0d45ae7f32e2ab9cb1886b230 /src/gtkext
parent5ed40f0afbd58fbfdf05be7b2a10ab8d0819759f (diff)
Displayed tooltips for graph view edges.
Diffstat (limited to 'src/gtkext')
-rw-r--r--src/gtkext/graph/cluster.c25
-rw-r--r--src/gtkext/graph/edge.c39
-rw-r--r--src/gtkext/graph/edge.h36
-rw-r--r--src/gtkext/gtkgraphdisplay.c71
4 files changed, 151 insertions, 20 deletions
diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c
index c4deeaa..765bbac 100644
--- a/src/gtkext/graph/cluster.c
+++ b/src/gtkext/graph/cluster.c
@@ -460,6 +460,8 @@ static gint compute_leaving_link_position(const leaving_link_t *link)
static incoming_link_t *create_incoming_link(GGraphCluster *owner, InstructionLinkType type, leaving_link_t *other)
{
incoming_link_t *result; /* Structure à retourner */
+ GCodeBlock *src; /* Bloc d'origine du lien */
+ GCodeBlock *dst; /* Bloc de destination du lien */
result = malloc(sizeof(incoming_link_t));
@@ -467,14 +469,23 @@ static incoming_link_t *create_incoming_link(GGraphCluster *owner, InstructionLi
result->type = type;
+ src = other->owner->block;
+ dst = owner->block;
+
if (type == ILT_JUMP_IF_TRUE)
- result->edge = g_graph_edge_new_true(&other->start[0], &other->start[1], &result->end[0], &result->end[1]);
+ result->edge = g_graph_edge_new_true(src, dst,
+ &other->start[0], &other->start[1],
+ &result->end[0], &result->end[1]);
else if (type == ILT_JUMP_IF_FALSE)
- result->edge = g_graph_edge_new_false(&other->start[0], &other->start[1], &result->end[0], &result->end[1]);
+ result->edge = g_graph_edge_new_false(src, dst,
+ &other->start[0], &other->start[1],
+ &result->end[0], &result->end[1]);
else
- result->edge = g_graph_edge_new(&other->start[0], &other->start[1], &result->end[0], &result->end[1]);
+ result->edge = g_graph_edge_new(src, dst,
+ &other->start[0], &other->start[1],
+ &result->end[0], &result->end[1]);
result->other = other;
@@ -499,6 +510,8 @@ static incoming_link_t *create_incoming_link(GGraphCluster *owner, InstructionLi
static incoming_link_t *create_incoming_loop_link(GGraphCluster *owner, const GdkPoint *midpts, leaving_link_t *other)
{
incoming_link_t *result; /* Structure à retourner */
+ GCodeBlock *src; /* Bloc d'origine du lien */
+ GCodeBlock *dst; /* Bloc de destination du lien */
result = malloc(sizeof(incoming_link_t));
@@ -506,7 +519,11 @@ static incoming_link_t *create_incoming_loop_link(GGraphCluster *owner, const Gd
result->type = ILT_LOOP;
- result->edge = g_graph_edge_new_loop(&other->start[0], &other->start[1],
+ src = other->owner->block;
+ dst = owner->block;
+
+ result->edge = g_graph_edge_new_loop(src, dst,
+ &other->start[0], &other->start[1],
&midpts[0], &midpts[1],
&result->end[0], &result->end[1]);
diff --git a/src/gtkext/graph/edge.c b/src/gtkext/graph/edge.c
index 9a2f848..20f1988 100644
--- a/src/gtkext/graph/edge.c
+++ b/src/gtkext/graph/edge.c
@@ -36,6 +36,9 @@ struct _GGraphEdge
{
GObject parent; /* A laisser en premier */
+ GCodeBlock *src; /* Bloc d'origine du lien */
+ GCodeBlock *dst; /* Bloc de destination du lien */
+
EdgeColor color; /* Couleur du rendu */
union
@@ -137,6 +140,9 @@ static void g_graph_edge_init(GGraphEdge *edge)
static void g_graph_edge_dispose(GGraphEdge *edge)
{
+ g_clear_object(&edge->src);
+ g_clear_object(&edge->dst);
+
G_OBJECT_CLASS(g_graph_edge_parent_class)->dispose(G_OBJECT(edge));
}
@@ -177,12 +183,18 @@ static void g_graph_edge_finalize(GGraphEdge *edge)
* *
******************************************************************************/
-GGraphEdge *_g_graph_edge_new(const GdkPoint **templates, size_t count, EdgeColor color)
+GGraphEdge *_g_graph_edge_new(GCodeBlock *src, GCodeBlock *dst, const GdkPoint **templates, size_t count, EdgeColor color)
{
GGraphEdge *result; /* Structure à retourner */
result = g_object_new(G_TYPE_GRAPH_EDGE, NULL);
+ result->src = src;
+ result->dst = dst;
+
+ g_object_ref(G_OBJECT(src));
+ g_object_ref(G_OBJECT(dst));
+
result->color = color;
assert(count == 4 || count == 6);
@@ -200,6 +212,31 @@ GGraphEdge *_g_graph_edge_new(const GdkPoint **templates, size_t count, EdgeColo
/******************************************************************************
* *
* Paramètres : edge = ligne de rendu à consulter. *
+* src = bloc d'origine du lien. [OUT] *
+* dst = bloc de destination du lien. [OUT] *
+* *
+* Description : Fournit les deux blocs aux extrémités d'un lien. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_graph_edge_get_boundaries(const GGraphEdge *edge, GCodeBlock **src, GCodeBlock **dst)
+{
+ *src = edge->src;
+ *dst = edge->dst;
+
+ g_object_ref(G_OBJECT(*src));
+ g_object_ref(G_OBJECT(*dst));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : edge = ligne de rendu à consulter. *
* x1 = abscisse du point de départ de la ligne. [OUT] *
* x2 = abscisse du point d'arrivée de la ligne. [OUT] *
* *
diff --git a/src/gtkext/graph/edge.h b/src/gtkext/graph/edge.h
index e905685..ec33544 100644
--- a/src/gtkext/graph/edge.h
+++ b/src/gtkext/graph/edge.h
@@ -30,13 +30,16 @@
#include <gtk/gtk.h>
+#include "../../analysis/disass/block.h"
-#define G_TYPE_GRAPH_EDGE g_graph_edge_get_type()
-#define G_GRAPH_EDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GRAPH_EDGE, GGraphEdge))
-#define G_IS_GRAPH_EDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GRAPH_EDGE))
-#define G_GRAPH_EDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GRAPH_EDGE, GGraphEdgeClass))
-#define G_IS_GRAPH_EDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GRAPH_EDGE))
-#define G_GRAPH_EDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_EDGE, GGraphEdgeClass))
+
+
+#define G_TYPE_GRAPH_EDGE g_graph_edge_get_type()
+#define G_GRAPH_EDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GRAPH_EDGE, GGraphEdge))
+#define G_IS_GRAPH_EDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GRAPH_EDGE))
+#define G_GRAPH_EDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GRAPH_EDGE, GGraphEdgeClass))
+#define G_IS_GRAPH_EDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GRAPH_EDGE))
+#define G_GRAPH_EDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GRAPH_EDGE, GGraphEdgeClass))
/* Lien graphique entre deux noeuds graphiques (instance) */
@@ -68,19 +71,22 @@ typedef enum _EdgeColor
GType g_graph_edge_get_type(void);
/* Etablit un lien graphique entre deux noeuds graphiques. */
-GGraphEdge *_g_graph_edge_new(const GdkPoint **, size_t, EdgeColor);
+GGraphEdge *_g_graph_edge_new(GCodeBlock *, GCodeBlock *, const GdkPoint **, size_t, EdgeColor);
+
+#define g_graph_edge_new(src, dst, pts0, pts1, pte0, pte1) \
+ _g_graph_edge_new(src, dst, (const GdkPoint *[]) { pts0, pts1, pte0, pte1 }, 4, EGC_DEFAULT)
-#define g_graph_edge_new(pts0, pts1, pte0, pte1) \
- _g_graph_edge_new((const GdkPoint *[]) { pts0, pts1, pte0, pte1 }, 4, EGC_DEFAULT)
+#define g_graph_edge_new_true(src, dst, pts0, pts1, pte0, pte1) \
+ _g_graph_edge_new(src, dst, (const GdkPoint *[]) { pts0, pts1, pte0, pte1 }, 4, EGC_GREEN)
-#define g_graph_edge_new_true(pts0, pts1, pte0, pte1) \
- _g_graph_edge_new((const GdkPoint *[]) { pts0, pts1, pte0, pte1 }, 4, EGC_GREEN)
+#define g_graph_edge_new_false(src, dst, pts0, pts1, pte0, pte1) \
+ _g_graph_edge_new(src, dst, (const GdkPoint *[]) { pts0, pts1, pte0, pte1 }, 4, EGC_RED)
-#define g_graph_edge_new_false(pts0, pts1, pte0, pte1) \
- _g_graph_edge_new((const GdkPoint *[]) { pts0, pts1, pte0, pte1 }, 4, EGC_RED)
+#define g_graph_edge_new_loop(src, dst, pts0, pts1, ptl0, ptl1, pte0, pte1) \
+ _g_graph_edge_new(src, dst, (const GdkPoint *[]) { pts0, pts1, ptl0, ptl1, pte0, pte1 }, 6, EGC_BLUE)
-#define g_graph_edge_new_loop(pts0, pts1, ptl0, ptl1, pte0, pte1) \
- _g_graph_edge_new((const GdkPoint *[]) { pts0, pts1, ptl0, ptl1, pte0, pte1 }, 6, EGC_BLUE)
+/* Fournit les deux blocs aux extrémités d'un lien. */
+void g_graph_edge_get_boundaries(const GGraphEdge *, GCodeBlock **, GCodeBlock **);
/* Fournit les abscisses des points extrèmes de la ligne. */
void g_graph_edge_get_x_borders(const GGraphEdge *, gint *, gint *);
diff --git a/src/gtkext/gtkgraphdisplay.c b/src/gtkext/gtkgraphdisplay.c
index 0915f3a..0865e04 100644
--- a/src/gtkext/gtkgraphdisplay.c
+++ b/src/gtkext/gtkgraphdisplay.c
@@ -27,11 +27,15 @@
#include <assert.h>
+#include <i18n.h>
+
+
#include "gtkblockdisplay.h"
#include "gtkbufferdisplay.h"
#include "gtkdisplaypanel-int.h"
#include "graph/cluster.h"
#include "../analysis/routine.h"
+#include "../common/extstr.h"
#include "../format/format.h"
#include "../glibext/gbinarycursor.h"
#include "../glibext/gloadedpanel.h"
@@ -115,6 +119,9 @@ static gboolean gtk_graph_display_button_release(GtkWidget *, GdkEventButton *,
/* Assure la suivi des déplacements de souris sur le composant. */
static gboolean gtk_graph_display_motion_notify(GtkWidget *, GdkEventMotion *, GtkGraphDisplay *);
+/* Prépare l'affichage d'une astuce. */
+static gboolean gtk_graph_display_query_tooltip(GtkWidget *, gint, gint, gboolean, GtkTooltip *, GtkGraphDisplay *);
+
/* Ajuste au besoin la zone affichée pour un curseur. */
static void gtk_graph_display_prepare_for_cursor(GtkGraphDisplay *, const GLineCursor *);
@@ -213,6 +220,10 @@ static void gtk_graph_display_init(GtkGraphDisplay *display)
G_CALLBACK(gtk_graph_display_button_release), display);
g_signal_connect(G_OBJECT(display->support), "motion-notify-event",
G_CALLBACK(gtk_graph_display_motion_notify), display);
+ g_signal_connect(G_OBJECT(display->support), "query-tooltip",
+ G_CALLBACK(gtk_graph_display_query_tooltip), display);
+
+ g_object_set(G_OBJECT(display->support), "has-tooltip", TRUE, NULL);
gtk_widget_add_events(display->support,
GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
@@ -649,6 +660,66 @@ static gboolean gtk_graph_display_motion_notify(GtkWidget *widget, GdkEventMotio
/******************************************************************************
* *
+* Paramètres : widget = composant GTK visé par l'opération. *
+* x = abscisse de la position du message. *
+* y = ordonnée de la position du message. *
+* keyboard = indique une demande suite à obtiention du focus. *
+* tooltip = astuce à compléter. [OUT] *
+* display = support maître à consulter. *
+* *
+* Description : Prépare l'affichage d'une astuce. *
+* *
+* Retour : TRUE pour un affichage validé, FALSE sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_graph_display_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard, GtkTooltip *tooltip, GtkGraphDisplay *display)
+{
+ gboolean result; /* Bilan à retourner */
+ GCodeBlock *src; /* Bloc d'origine du lien */
+ GCodeBlock *dst; /* Bloc de destination du lien */
+ char *info; /* Information à faire paraître*/
+ char *desc; /* Description d'un bloc */
+
+ result = FALSE;
+
+ if (display->hl_edge_index < display->edges_count)
+ {
+ g_graph_edge_get_boundaries(display->edges[display->hl_edge_index], &src, &dst);
+
+ info = stradd(NULL, _("<b>Source:</b> "));
+
+ desc = g_code_block_build_tooltip(src);
+ info = stradd(info, desc);
+ free(desc);
+
+ info = stradd(info, "\n\n");
+
+ info = stradd(info, _("<b>Destination:</b> "));
+
+ desc = g_code_block_build_tooltip(dst);
+ info = stradd(info, desc);
+ free(desc);
+
+ gtk_tooltip_set_markup(tooltip, info);
+ free(info);
+
+ g_object_unref(G_OBJECT(src));
+ g_object_unref(G_OBJECT(dst));
+
+ result = TRUE;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : display = composant GTK à mettre à jour. *
* cursor = emplacement à présenter à l'écran. *
* *