diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2013-08-17 21:54:56 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2013-08-17 21:54:56 (GMT) |
commit | e53684bebd74d0a8ade79082c618ebb21bdea361 (patch) | |
tree | 1a9e772134f2fea48ec06c78de1d2ceaef6b69ad /src/gtkext/graph/nodes/flow.c | |
parent | a7d77562cd63f6cf0856b4cc19e245072af86f69 (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.c | 413 |
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); */ |