summaryrefslogtreecommitdiff
path: root/src/gtkext/graph/nodes/flow.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2013-08-17 21:54:56 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2013-08-17 21:54:56 (GMT)
commite53684bebd74d0a8ade79082c618ebb21bdea361 (patch)
tree1a9e772134f2fea48ec06c78de1d2ceaef6b69ad /src/gtkext/graph/nodes/flow.c
parenta7d77562cd63f6cf0856b4cc19e245072af86f69 (diff)
Replaced some parts of the graph computing for better results.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@356 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/gtkext/graph/nodes/flow.c')
-rw-r--r--src/gtkext/graph/nodes/flow.c413
1 files changed, 109 insertions, 304 deletions
diff --git a/src/gtkext/graph/nodes/flow.c b/src/gtkext/graph/nodes/flow.c
index de434ab..fad520d 100644
--- a/src/gtkext/graph/nodes/flow.c
+++ b/src/gtkext/graph/nodes/flow.c
@@ -49,8 +49,6 @@ struct _GFlowNode
GFlowBlock *block; /* Bloc d'exécution associé */
GtkBufferView *view; /* Représentation graphique */
- GtkAllocation alloc; /* Emplacement du bloc rattaché*/
-
node_slot_t *entries; /* Positions des pts d'entrées */
size_t entries_count; /* Nombre de ces points */
node_slot_t *exits; /* Positions des pts de sorties*/
@@ -84,17 +82,8 @@ static void g_flow_node_finalize(GFlowNode *);
/* Fournit le rang du noeud dans le graphique. */
static unsigned int g_flow_node_get_rank(const GFlowNode *);
-/* Réinitialise la position d'un noeud d'encapsulation. */
-static void g_flow_node_reset_position(GFlowNode *);
-
-/* Altère la position du noeud d'encapsulation. */
-static void g_flow_node_set_position(GFlowNode *, gint *, gint *);
-
-/* Fournit la position du noeud d'encapsulation. */
-static void g_flow_node_get_position(const GFlowNode *, gint *, gint *);
-
-/* Indique l'espace requis pour un noeud d'encapsulation. */
-static GtkAllocation g_flow_node_get_allocation(const GFlowNode *);
+/* Organise le contenu du noeud selon l'axe des abscisses. */
+static void g_flow_node_prepare_x_line(GFlowNode *, GGraphNode *);
/* Parcourt tous les blocs d'instructions dans un ordre donné. */
static bool g_flow_node_visit_flow_nodes(GFlowNode *, graph_node_visitor_cb, void *);
@@ -166,15 +155,9 @@ static void g_flow_node_init(GFlowNode *node)
base = G_GRAPH_NODE(node);
base->get_rank = (get_node_rank_fc)g_flow_node_get_rank;
- base->reset_pos = (node_reset_pos_fc)g_flow_node_reset_position;
- base->set_pos = (node_set_pos_fc)g_flow_node_set_position;
- base->get_pos = (node_get_pos_fc)g_flow_node_get_position;
- base->get_alloc = (node_get_alloc_fc)g_flow_node_get_allocation;
+ base->prepare_x = (node_prepare_x_fc)g_flow_node_prepare_x_line;
base->visit = (visit_flow_nodes_fc)g_flow_node_visit_flow_nodes;
- node->alloc.x = UNINITIALIZED_NODE_POS;
- node->alloc.y = UNINITIALIZED_NODE_POS;
-
}
@@ -261,8 +244,8 @@ GGraphNode *g_flow_node_new(GFlowBlock *block, GtkBufferView *view)
gtk_widget_size_request(GTK_WIDGET(result->view), &requisition);
- result->alloc.width = requisition.width;
- result->alloc.height = requisition.height;
+ G_GRAPH_NODE(result)->alloc.width = requisition.width;
+ G_GRAPH_NODE(result)->alloc.height = requisition.height;
g_flow_node_setup_entry_slots(result);
g_flow_node_setup_exit_slots(result);
@@ -293,9 +276,10 @@ static unsigned int g_flow_node_get_rank(const GFlowNode *node)
/******************************************************************************
* *
-* Paramètres : node = noeud graphique à manipuler. *
+* Paramètres : node = noeud d'encapsulation à traiter. *
+* nodes = ensemble des noeuds en place. *
* *
-* Description : Réinitialise la position d'un noeud d'encapsulation. *
+* Description : Organise le contenu du noeud selon l'axe des abscisses. *
* *
* Retour : - *
* *
@@ -303,83 +287,113 @@ static unsigned int g_flow_node_get_rank(const GFlowNode *node)
* *
******************************************************************************/
-static void g_flow_node_reset_position(GFlowNode *node)
+static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
{
- GtkRequisition requisition; /* Taille à l'écran actuelle */
+ GGraphNode *base; /* Autre vision de l'instance */
+ GArchInstruction *last; /* Dernière instr. du noeud */
+ GFlowNode *target; /* Bloc visé par le lien */
+ node_slot_t *dest_slot; /* Accrochage d'arrivée */
+ pending_position pos; /* Position à transmettre */
+ GFlowNode *target_a; /* Bloc visé par le lien #a */
+ GFlowNode *target_b; /* Bloc visé par le lien #b */
+ unsigned int rank_a; /* Indice du rang associé #a */
+ unsigned int rank_b; /* Indice du rang associé #b */
+ GGraphNode *container; /* Conteneur à positionner */
- node->alloc.x = UNINITIALIZED_NODE_POS;
- node->alloc.y = UNINITIALIZED_NODE_POS;
+ base = G_GRAPH_NODE(node);
- gtk_widget_size_request(GTK_WIDGET(node->view), &requisition);
+ g_flow_block_get_boundary(node->block, NULL, &last);
- node->alloc.width = requisition.width;
- node->alloc.height = requisition.height;
+ switch (node->exits_count)
+ {
+ case 0:
+ break;
-}
+ case 1:
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à manipuler. *
-* x = éventuelle abscisse à intégrer ou NULL. *
-* y = éventuelle ordonnée à intégrer ou NULL. *
-* *
-* Description : Altère la position du noeud d'encapsulation. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (node->exits[0].type == ILT_LOOP)
+ break;
-static void g_flow_node_set_position(GFlowNode *node, gint *x, gint *y)
-{
- if (x != NULL) node->alloc.x = *x;
- if (y != NULL) node->alloc.y = *y;
+ target = G_FLOW_NODE(find_node_for_instruction(nodes, node->exits[0].instr));
-}
+ dest_slot = g_flow_node_get_slot(target, true,
+ last, node->exits[0].group_index);
+ pos.direct_x = g_flow_node_get_slot_offset(target, true, dest_slot);
+ pos.direct_x = (G_GRAPH_NODE(target)->alloc.width / 2) - pos.direct_x;
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* x = éventuelle abscisse à recevoir ou NULL. [OUT] *
-* y = éventuelle ordonnée à recevoir ou NULL. [OUT] *
-* *
-* Description : Fournit la position du noeud d'encapsulation. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (target->entries_count == 1)
+ g_graph_node_set_pending_position(G_GRAPH_NODE(target), PPF_DIRECT_X, pos, base);
-static void g_flow_node_get_position(const GFlowNode *node, gint *x, gint *y)
-{
- if (x != NULL) *x = node->alloc.x;
- if (y != NULL) *y = node->alloc.y;
+ break;
-}
+ case 2:
+ target_a = G_FLOW_NODE(find_node_for_instruction(nodes, node->exits[0].instr));
+ target_b = G_FLOW_NODE(find_node_for_instruction(nodes, node->exits[1].instr));
-/******************************************************************************
-* *
-* Paramètres : node = noeud graphique à consulter. *
-* *
-* Description : Indique l'espace requis pour un noeud d'encapsulation. *
-* *
-* Retour : Espace constitué, entièrement ou non. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ rank_a = g_flow_node_get_rank(target_a);
+ rank_b = g_flow_node_get_rank(target_b);
-static GtkAllocation g_flow_node_get_allocation(const GFlowNode *node)
-{
- GtkAllocation result; /* Valeurs à retourner */
+ if (rank_a == rank_b)
+ break;
- result = node->alloc;
+ /* Alignement d'un bloc lié */
- return result;
+ if (rank_a > rank_b)
+ {
+ /* Seuil vertical pour un côté */
+
+ container = g_graph_node_find_container_at_same_level(nodes,
+ G_GRAPH_NODE(node),
+ G_GRAPH_NODE(target_b));
+
+ if (container == NULL) container = G_GRAPH_NODE(target_b);
+
+ pos.left_margin = g_flow_node_get_slot_offset(node, false, &node->exits[0]);
+ g_graph_node_set_pending_position(container, PPF_LEFT_MARGIN, pos, base);
+
+ /* Trait vertical de l'autre côté... */
+
+ pos.direct_x = pos.left_margin;
+
+ dest_slot = g_flow_node_get_slot(target_a, true,
+ last, node->exits[0].group_index);
+
+ pos.direct_x -= g_flow_node_get_slot_offset(target_a, true, dest_slot);
+
+ g_graph_node_set_pending_position(G_GRAPH_NODE(target_a), PPF_DIRECT_X, pos, base);
+
+ }
+ else
+ {
+ /* Seuil vertical pour un côté */
+
+ container = g_graph_node_find_container_at_same_level(nodes,
+ G_GRAPH_NODE(node),
+ G_GRAPH_NODE(target_a));
+
+ if (container == NULL) container = G_GRAPH_NODE(target_a);
+
+ pos.right_margin = g_flow_node_get_slot_offset(node, false, &node->exits[1]);
+ g_graph_node_set_pending_position(container, PPF_RIGHT_MARGIN, pos, base);
+
+ /* Trait vertical de l'autre côté... */
+
+ pos.direct_x = pos.right_margin;
+
+ dest_slot = g_flow_node_get_slot(target_b, true,
+ last, node->exits[1].group_index);
+
+ pos.direct_x -= g_flow_node_get_slot_offset(target_b, true, dest_slot);
+
+ g_graph_node_set_pending_position(G_GRAPH_NODE(target_b), PPF_DIRECT_X, pos, base);
+
+ }
+
+ break;
+
+ }
}
@@ -463,7 +477,7 @@ void g_flow_node_register_rank(const GFlowNode *node, GGraphRanks *ranks)
index = g_flow_node_get_rank(node);
- g_graph_ranks_set_min_height(ranks, index, node->alloc.height);
+ g_graph_ranks_set_min_height(ranks, index, G_GRAPH_NODE(node)->alloc.height);
}
@@ -487,219 +501,7 @@ void g_flow_node_apply_rank(GFlowNode *node, GGraphRanks *ranks)
index = g_flow_node_get_rank(node);
- node->alloc.y = g_graph_ranks_get_y_for_rank(ranks, index);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : node = noeud d'encapsulation à traiter. *
-* nodes = ensemble des noeuds en place. *
-* *
-* Description : Organise le contenu du noeud selon l'axe des abscisses. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_flow_node_organize_x_line(GFlowNode *node, GGraphNode *nodes)
-{
- GArchInstruction *last; /* Dernière instr. du noeud */
- GFlowNode *target; /* Bloc visé par le lien */
- node_slot_t *dest_slot; /* Accrochage d'arrivée */
- gint offset; /* Décallage d'une accroche */
- gint ref_pos; /* Position de référence */
- GdkPoint ref; /* Position de référence */
- GFlowNode *target_a; /* Bloc visé par le lien #a */
- GFlowNode *target_b; /* Bloc visé par le lien #b */
- unsigned int rank_a; /* Indice du rang associé #a */
- unsigned int rank_b; /* Indice du rang associé #b */
- GGraphNode *container; /* Conteneur à positionner */
-
- g_flow_block_get_boundary(node->block, NULL, &last);
-
- switch (node->exits_count)
- {
- case 1:
-
- if (node->exits[0].type == ILT_LOOP)
- break;
-
- target = G_FLOW_NODE(find_node_for_instruction(nodes, node->exits[0].instr));
-
-#if 0
- /**
- * La recherche ne se faisant que dans le sous-ensemble des blocs voisins,
- * on écarte des recherches les cibles se situant dans des blocs virtuels parents.
- */
- if (target == NULL)
- break;
-#endif
-
- if (g_graph_node_has_x_position(G_GRAPH_NODE(target)))
- break;
-
- dest_slot = g_flow_node_get_slot(target, true,
- last, node->exits[0].group_index);
-
- offset = g_flow_node_get_slot_offset(target, true, dest_slot);
- offset = (target->alloc.width / 2) - offset;
-
- if (G_GRAPH_NODE(target)->pending_x == 0)
-
- g_graph_node_set_pending_position(G_GRAPH_NODE(target), (gint []) { offset }, NULL);
-
- break;
-
- case 2:
-
- target_a = G_FLOW_NODE(find_node_for_instruction(nodes, node->exits[0].instr));
- target_b = G_FLOW_NODE(find_node_for_instruction(nodes, node->exits[1].instr));
-
-#if 0
- /**
- * La recherche ne se faisant que dans le sous-ensemble des blocs voisins,
- * on écarte des recherches les cibles se situant dans des blocs virtuels parents.
- */
- if (target_a == NULL || target_b == NULL)
- break;
-#endif
-
- /*
- if (g_graph_node_has_x_position(G_GRAPH_NODE(target_a))
- || g_graph_node_has_x_position(G_GRAPH_NODE(target_b)))
- break;
- */
-
- rank_a = g_flow_node_get_rank(target_a);
- rank_b = g_flow_node_get_rank(target_b);
-
- printf("\nRANKS : a=%d vs b=%d\n", rank_a, rank_b);
-
- if (rank_a == rank_b)
- break;
-
- /* Alignement d'un bloc lié */
-
- if (rank_a > rank_b)
- {
-
- g_graph_node_get_position(G_GRAPH_NODE(node), &ref_pos, NULL);
- ref_pos += (node->alloc.width / 2);
- //printf("parent = %d mid = %d\n", ref_pos, (node->alloc.width / 2));
-
-
- ref_pos += g_flow_node_get_slot_offset(node, false, &node->exits[0]);
- ref_pos -= (node->alloc.width / 2);
-
- //printf("ref_pos = %d mid = %d\n", ref_pos, node->alloc.width / 2);
-
-
- dest_slot = g_flow_node_get_slot(target_a, true,
- last, node->exits[0].group_index);
-
- offset = g_flow_node_get_slot_offset(target_a, true, dest_slot);
-
- //printf("offset = %d mid = %d\n", offset, (target_a->alloc.width / 2));
-
- offset = (target_a->alloc.width / 2) - offset;
- offset += ref_pos;
-
- //ref = g_flow_node_get_point_from_slot(node, false, &node->exits[0]);
-
-
-
- printf("> offset = %d\n", offset);
-
-
- //offset += (ref.x < 0 ? - ref.x : ref.x);
-
-#if 1
-
- if (!g_graph_node_has_x_position(G_GRAPH_NODE(target_a))
- && G_GRAPH_NODE(target_a)->pending_x == 0)
-
- g_graph_node_set_pending_position(G_GRAPH_NODE(target_a),
- (gint []) { offset }, NULL);
-
- else printf("pending...\n");
-
-#endif
-
- }
- else
- {
- dest_slot = g_flow_node_get_slot(target_b, true,
- last, node->exits[1].group_index);
-
- offset = g_flow_node_get_slot_offset(target_b, true, dest_slot);
- offset = (target_b->alloc.width / 2) - offset;
-
- ref = g_flow_node_get_point_from_slot(node, false, &node->exits[1]);
- //offset += (ref.x < 0 ? - ref.x : ref.x);
-
-
-
- if (G_GRAPH_NODE(target_b)->pending_x == 0)
-
- g_graph_node_set_pending_position(G_GRAPH_NODE(target_b),
- (gint []) { offset }, NULL);
-
- }
-
- /* Balance du bloc non aligné */
-
- if (rank_a > rank_b)
- {
- container = g_graph_node_find_container_at_same_level(nodes,
- G_GRAPH_NODE(node),
- G_GRAPH_NODE(target_b));
-
- if (container == NULL) break;
-
-
- printf("----\n");
- printf("node = %p (%d)\n", node, g_graph_node_get_rank(G_GRAPH_NODE(node)));
- printf("target a = %p\n", target_a);
- printf("target b = %p\n", target_b);
- printf("container= %p (%d)\n", container, g_graph_node_get_rank(G_GRAPH_NODE(container)));
-
- printf("(%p) container %p --> %d\n", nodes, container, ref.x + 20);
-
- printf("has pos ? %d\n", g_graph_node_has_x_position(container));
-
-
- dest_slot = g_flow_node_get_slot(target_a, true,
- last, node->exits[0].group_index);
-
- offset += g_flow_node_get_slot_offset(target_a, true, dest_slot);
-
-
- offset += 200;
-
- //if (ref.x < -10000)
- // printf(" !!!! REF.X = %d\n", ref.x);
-
- //g_graph_node_set_position(container, (gint []) { ref.x + 20 }, NULL);
-
-
- printf(">> set offset : %d\n", offset + 50);
- printf(">> pending :: %d\n", G_GRAPH_NODE(container)->pending_x);
-
- g_graph_node_set_pending_position(container, (gint []) { offset + 50 }, NULL);
-
- }
-
-
- break;
-
-
- }
-
-
+ G_GRAPH_NODE(node)->alloc.y = g_graph_ranks_get_y_for_rank(ranks, index);
}
@@ -779,7 +581,7 @@ void g_flow_node_link(GFlowNode *node, GGraphLayout *layout, GGraphNode *nodes)
void g_flow_node_place(const GFlowNode *node, GtkGraphView *view)
{
- gtk_graph_view_put(view, GTK_WIDGET(node->view), &node->alloc);
+ gtk_graph_view_put(view, GTK_WIDGET(node->view), &G_GRAPH_NODE(node)->alloc);
}
@@ -954,7 +756,7 @@ static gint g_flow_node_get_slot_offset(const GFlowNode *node, bool entry, const
}
slots_width = (count - 1) * SPACE_BETWEEN_SLOT;
- slots_left = (node->alloc.width - slots_width) / 2;
+ slots_left = (G_GRAPH_NODE(node)->alloc.width - slots_width) / 2;
index = (slot - slots);
/* BUG_ON(index >= count); */
@@ -982,6 +784,7 @@ static gint g_flow_node_get_slot_offset(const GFlowNode *node, bool entry, const
GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *node, bool entry, const node_slot_t *slot)
{
+ GGraphNode *base; /* Accès rapides */
GdkPoint result; /* Position à retourner */
node_slot_t *slots; /* Accroches à parcourir */
size_t count; /* Nombre de ces points */
@@ -989,9 +792,11 @@ GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *node, bool entry, cons
gint slots_left; /* Abscisse de la première */
size_t index; /* Indice de l'accroche visée */
+ base = G_GRAPH_NODE(node);
+
if (entry)
{
- result.y = node->alloc.y;
+ result.y = base->alloc.y;
slots = node->entries;
count = node->entries_count;
@@ -999,7 +804,7 @@ GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *node, bool entry, cons
}
else
{
- result.y = node->alloc.y + node->alloc.height;
+ result.y = base->alloc.y + base->alloc.height;
slots = node->exits;
count = node->exits_count;
@@ -1008,7 +813,7 @@ GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *node, bool entry, cons
slots_width = (count - 1) * SPACE_BETWEEN_SLOT;
- slots_left = node->alloc.x + (node->alloc.width - slots_width) / 2;
+ slots_left = base->alloc.x + (base->alloc.width - slots_width) / 2;
index = (slot - slots)/* / sizeof(node_slot_t)*/;
/* BUG_ON(index >= count); */
@@ -1019,7 +824,7 @@ GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *node, bool entry, cons
#if 0
slots_width = (count - 1) * SPACE_BETWEEN_SLOT;
- slots_left = node->alloc.x + (node->alloc.width - slots_width) / 2;
+ slots_left = base->alloc.x + (base->alloc.width - slots_width) / 2;
index = (slot - slots)/* / sizeof(node_slot_t)*/;
/* BUG_ON(index >= count); */