diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2013-05-26 10:49:51 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2013-05-26 10:49:51 (GMT) |
commit | d80df591b6104c98d21e1db5143610fb84e35941 (patch) | |
tree | b17d441e544b68f8433c45ba8a177242317a3bce /src/gtkext/graph/nodes | |
parent | 114e769bc9c3dc48f0293f080d687451e32220e3 (diff) |
Improved the graph rendering.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@347 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/gtkext/graph/nodes')
-rw-r--r-- | src/gtkext/graph/nodes/flow.c | 274 | ||||
-rw-r--r-- | src/gtkext/graph/nodes/flow.h | 3 | ||||
-rw-r--r-- | src/gtkext/graph/nodes/virtual.c | 95 | ||||
-rw-r--r-- | src/gtkext/graph/nodes/virtual.h | 2 |
4 files changed, 341 insertions, 33 deletions
diff --git a/src/gtkext/graph/nodes/flow.c b/src/gtkext/graph/nodes/flow.c index 1848048..de434ab 100644 --- a/src/gtkext/graph/nodes/flow.c +++ b/src/gtkext/graph/nodes/flow.c @@ -113,6 +113,10 @@ static void g_flow_node_setup_exit_slots(GFlowNode *); /* Etablit un lien entre deux noeuds graphiques. */ static node_slot_t *g_flow_node_get_slot(const GFlowNode *, bool, GArchInstruction *, size_t); +/* Localise un point d'accroche à un noeud graphique. */ +static gint g_flow_node_get_slot_offset(const GFlowNode *, bool, const node_slot_t *); + + /* Indique le type définit par la GLib pour l'encapsulation d'un bloc d'exécution. */ @@ -488,6 +492,217 @@ void g_flow_node_apply_rank(GFlowNode *node, GGraphRanks *ranks) } +/****************************************************************************** +* * +* 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; + + + } + + + +} + /****************************************************************************** * * @@ -712,6 +927,53 @@ static node_slot_t *g_flow_node_get_slot(const GFlowNode *node, bool entry, GArc * * * Description : Localise un point d'accroche à un noeud graphique. * * * +* Retour : Décallage relatif pour l'accroche fournie. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static gint g_flow_node_get_slot_offset(const GFlowNode *node, bool entry, const node_slot_t *slot) +{ + gint result; /* Valeur à retourner */ + node_slot_t *slots; /* Accroches à parcourir */ + size_t count; /* Nombre de ces points */ + gint slots_width; /* Largeur des accroches */ + gint slots_left; /* Abscisse de la première */ + size_t index; /* Indice de l'accroche visée */ + + if (entry) + { + slots = node->entries; + count = node->entries_count; + } + else + { + slots = node->exits; + count = node->exits_count; + } + + slots_width = (count - 1) * SPACE_BETWEEN_SLOT; + slots_left = (node->alloc.width - slots_width) / 2; + + index = (slot - slots); + /* BUG_ON(index >= count); */ + + result = slots_left + index * SPACE_BETWEEN_SLOT; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : node = noeud graphique à consulter. * +* entry = indique le type d'accrochage recherché. * +* slot = accroche dont l'emplacement est à définir. * +* * +* Description : Localise un point d'accroche à un noeud graphique. * +* * * Retour : Emplacement réservé pour l'accroche fournie. * * * * Remarques : - * @@ -744,6 +1006,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; @@ -752,6 +1015,17 @@ GdkPoint g_flow_node_get_point_from_slot(const GFlowNode *node, bool entry, cons result.x = slots_left + index * SPACE_BETWEEN_SLOT; + + +#if 0 + slots_width = (count - 1) * SPACE_BETWEEN_SLOT; + slots_left = node->alloc.x + (node->alloc.width - slots_width) / 2; + + index = (slot - slots)/* / sizeof(node_slot_t)*/; + /* BUG_ON(index >= count); */ + + result.x = slots_left + index * SPACE_BETWEEN_SLOT; +#endif return result; } diff --git a/src/gtkext/graph/nodes/flow.h b/src/gtkext/graph/nodes/flow.h index 5a6268e..5c99284 100644 --- a/src/gtkext/graph/nodes/flow.h +++ b/src/gtkext/graph/nodes/flow.h @@ -70,6 +70,9 @@ void g_flow_node_apply_rank(GFlowNode *, GGraphRanks *); /* Etablit les liaison entre un noeud et ses suivants. */ void g_flow_node_link(GFlowNode *, GGraphLayout *, GGraphNode *); +/* Organise le contenu du noeud selon l'axe des abscisses. */ +void g_flow_node_organize_x_line(GFlowNode *, GGraphNode *); + /* Place un noeud sur son support final. */ void g_flow_node_place(const GFlowNode *, GtkGraphView *); diff --git a/src/gtkext/graph/nodes/virtual.c b/src/gtkext/graph/nodes/virtual.c index e13dfc8..05a7063 100644 --- a/src/gtkext/graph/nodes/virtual.c +++ b/src/gtkext/graph/nodes/virtual.c @@ -129,7 +129,7 @@ static bool g_virtual_node_visit_flow_nodes(GVirtualNode *, graph_node_visitor_c static GGraphNode *g_virtual_node_find_container(GVirtualNode *, GGraphNode *); /* Définit les abscisses relatives du contenu d'un noeud. */ -static void g_virtual_node_setup_x_line(GVirtualNode *); +static void g_virtual_node_setup_x_line(GVirtualNode *, GGraphNode *); @@ -432,9 +432,46 @@ static void g_virtual_node_reset_position(GVirtualNode *node) static void g_virtual_node_set_position(GVirtualNode *node, gint *x, gint *y) { + gint old_x; /* Sauvegarde des abscisses */ + gint old_y; /* Sauvegarde des ordonnées */ + gint off_x; /* Décallage sur les abscisses */ + gint off_y; /* Décallage sur les ordonnées */ + gint pos_x; /* Nouvelle position #1 */ + gint pos_y; /* Nouvelle position #2 */ + size_t i; /* Boucle de parcours */ + + + //if (x != NULL) printf("-- setX -- %p -> %d (old=%d)\n", node, *x, node->x); + + old_x = node->x; + old_y = node->y; + + + if (x != NULL) node->x = *x; if (y != NULL) node->y = *y; + off_x = (old_x != UNINITIALIZED_NODE_POS && node->x != UNINITIALIZED_NODE_POS ? node->x - old_x : 0); + off_y = (old_y != UNINITIALIZED_NODE_POS ? node->y - old_y : node->y); + + //printf("offx = %d\n", off_x); + + + for (i = 0; i < node->count; i++) + { + g_graph_node_get_position(node->children[i], &pos_x, &pos_y); + + + if (x != NULL) pos_x += off_x; + + + g_graph_node_set_position(node->children[i], &pos_x, &pos_y); + + + } + + + } @@ -477,7 +514,6 @@ static GtkAllocation g_virtual_node_get_allocation(const GVirtualNode *node) GtkAllocation result; /* Valeurs à retourner */ gint margins; /* Bordures gauche et droite */ unsigned int last_rank; /* Détection de saut de rangs */ - size_t horiz_count; /* Quantité à l'horizontale */ size_t vert_count; /* Quantité à la verticale */ gint rank_width; /* Largeur d'un rang donné */ gint rank_height; /* Hauteur d'un rang donné */ @@ -503,7 +539,6 @@ static GtkAllocation g_virtual_node_get_allocation(const GVirtualNode *node) last_rank = -1; - horiz_count = 0; vert_count = 0; rank_width = 0; @@ -513,41 +548,36 @@ static GtkAllocation g_virtual_node_get_allocation(const GVirtualNode *node) { alloc = g_graph_node_get_allocation(node->children[i]); + /* Prise en compte de l'étage précédent */ if (last_rank != g_graph_node_get_rank(node->children[i])) { last_rank = g_graph_node_get_rank(node->children[i]); result.width = MAX(result.width, rank_width); - - /* - if (horiz_count > 0) - result.width = MAX(result.width, rank_width + (horiz_count - 1) * NODE_LEFT_MARGIN); - */ - result.height += rank_height; rank_width = 0; rank_height = 0; - horiz_count = 0; vert_count++; } - //rank_width += alloc.width; - if (rank_width > 0) rank_width += NODE_LEFT_MARGIN; - rank_width += alloc.width; - rank_height = MAX(rank_height, alloc.height); + /* Mise à jour de l'étage courant */ + + if (node->x == UNINITIALIZED_NODE_POS) + { + rank_width += alloc.width; + if (rank_width > 0) rank_width += NODE_LEFT_MARGIN; + } + else + rank_width = MAX(alloc.x + alloc.width - node->x, rank_width); - horiz_count++; + rank_height = MAX(rank_height, alloc.height); } result.width = MAX(result.width, rank_width); - /* - if (horiz_count > 0) - result.width = MAX(result.width, rank_width + (horiz_count - 1) * NODE_LEFT_MARGIN); - */ result.width += margins; @@ -747,7 +777,8 @@ vspan_slot_t g_virtual_node_reserve_span(GVirtualNode *node, unsigned int r1, un /****************************************************************************** * * -* Paramètres : node = noeud d'encapsulation à traiter. * +* Paramètres : node = noeud d'encapsulation à traiter. * +* nodes = ensemble des noeuds en place. * * * * Description : Organise le contenu du noeud selon l'axe des abscisses. * * * @@ -757,13 +788,13 @@ vspan_slot_t g_virtual_node_reserve_span(GVirtualNode *node, unsigned int r1, un * * ******************************************************************************/ -void g_virtual_node_organize_x_line(GVirtualNode *node) +void g_virtual_node_organize_x_line(GVirtualNode *node, GGraphNode *nodes) { size_t i; /* Boucle de parcours */ gint min; /* Valeur minimale rencontrée */ gint x; /* Position d'un sous-noeud */ - g_virtual_node_setup_x_line(node); + g_virtual_node_setup_x_line(node, nodes); min = 0; @@ -783,7 +814,8 @@ void g_virtual_node_organize_x_line(GVirtualNode *node) /****************************************************************************** * * -* Paramètres : node = noeud d'encapsulation à traiter. * +* Paramètres : node = noeud d'encapsulation à traiter. * +* nodes = ensemble des noeuds en place. * * * * Description : Définit les abscisses relatives du contenu d'un noeud. * * * @@ -793,7 +825,7 @@ void g_virtual_node_organize_x_line(GVirtualNode *node) * * ******************************************************************************/ -static void g_virtual_node_setup_x_line(GVirtualNode *node) +static void g_virtual_node_setup_x_line(GVirtualNode *node, GGraphNode *nodes) { unsigned int rank_0; /* Rang du premier sous-noeud */ unsigned int rank_1; /* Rang du second sous-noeud */ @@ -852,15 +884,10 @@ static void g_virtual_node_setup_x_line(GVirtualNode *node) /* Définitions éventuelles des emplacements liés */ if (G_IS_FLOW_NODE(child)) - { - + g_flow_node_organize_x_line(G_FLOW_NODE(child), nodes); - ; - - - } else if (G_IS_VIRTUAL_NODE(child)) - g_virtual_node_organize_x_line(G_VIRTUAL_NODE(child)); + g_virtual_node_organize_x_line(G_VIRTUAL_NODE(child), nodes); /*else BUG_ON(1); */ @@ -904,7 +931,11 @@ void g_virtual_node_offset_x_line(GVirtualNode *node, gint xoffset) g_graph_node_get_position(child, &x, NULL); - x += xoffset + padding; + printf("+++ [%p-%d/%p] offsetting %d(%d) + (%d / %d)\n", + node, g_graph_node_get_rank(G_GRAPH_NODE(node)), child, + node->x, G_GRAPH_NODE(node)->pending_x, x, x + xoffset + padding); + + x += node->x + xoffset + padding; g_graph_node_set_position(child, &x, NULL); } diff --git a/src/gtkext/graph/nodes/virtual.h b/src/gtkext/graph/nodes/virtual.h index 20106b6..a7a96d7 100644 --- a/src/gtkext/graph/nodes/virtual.h +++ b/src/gtkext/graph/nodes/virtual.h @@ -69,7 +69,7 @@ GGraphNode *g_virtual_node_get_child(const GVirtualNode *, size_t); vspan_slot_t g_virtual_node_reserve_span(GVirtualNode *, unsigned int, unsigned int, bool); /* Organise le contenu du noeud selon l'axe des abscisses. */ -void g_virtual_node_organize_x_line(GVirtualNode *); +void g_virtual_node_organize_x_line(GVirtualNode *, GGraphNode *); /* Procède à un décallage du contenu sur l'axe des abscisses. */ void g_virtual_node_offset_x_line(GVirtualNode *, gint); |