diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | src/gtkext/graph/layout.c | 58 | ||||
-rw-r--r-- | src/gtkext/graph/node-int.h | 34 | ||||
-rw-r--r-- | src/gtkext/graph/node.c | 165 | ||||
-rw-r--r-- | src/gtkext/graph/node.h | 38 | ||||
-rw-r--r-- | src/gtkext/graph/nodes/flow.c | 413 | ||||
-rw-r--r-- | src/gtkext/graph/nodes/flow.h | 3 | ||||
-rw-r--r-- | src/gtkext/graph/nodes/virtual.c | 480 | ||||
-rw-r--r-- | src/gtkext/graph/nodes/virtual.h | 6 | ||||
-rw-r--r-- | src/gtkext/graph/params.h | 6 |
10 files changed, 630 insertions, 587 deletions
@@ -1,3 +1,17 @@ +13-08-17 Cyrille Bagard <nocbos@gmail.com> + + * src/gtkext/graph/layout.c: + * src/gtkext/graph/node.c: + * src/gtkext/graph/node.h: + * src/gtkext/graph/node-int.h: + * src/gtkext/graph/nodes/flow.c: + * src/gtkext/graph/nodes/flow.h: + * src/gtkext/graph/nodes/virtual.c: + * src/gtkext/graph/nodes/virtual.h: + * src/gtkext/graph/params.h: + Replace some parts of the graph computing for better results. + + 13-08-13 Cyrille Bagard <nocbos@gmail.com> * src/analysis/disass/loop.c: diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c index 43caf44..9ac3ee3 100644 --- a/src/gtkext/graph/layout.c +++ b/src/gtkext/graph/layout.c @@ -587,10 +587,62 @@ GGraphLayout *g_graph_layout_new(GInstrBlock *blocks, GtkBufferView **views, siz g_graph_node_visit_nodes(result->nodes, (graph_node_visitor_cb)_register_cb, result); + bool _print_dbg_cb(GFlowNode *node, GNodeVisitState state, int *depth) + { + int i; + + if (state == GVS_ENTER || state == GVS_NODE) + { + for (i = 0; i < *depth; i++) + printf(" "); + + printf("- %p\n", node); + + } + + if (state == GVS_ENTER) (*depth)++; + else if (state == GVS_EXIT) (*depth)--; + + return true; + + } + + printf("==== graph ====\n"); + g_graph_node_visit_nodes(result->nodes, (graph_node_visitor_cb)_print_dbg_cb, (int []){ 0 }); + printf("\n"); + /* Actualisation... */ g_graph_layout_refresh(result); + bool _print_dbg_ext_cb(GGraphNode *node, GNodeVisitState state, int *depth) + { + int i; + GtkAllocation alloc; + + if (state == GVS_ENTER || state == GVS_NODE) + { + for (i = 0; i < *depth; i++) + printf(" "); + + alloc = g_graph_node_get_allocation(node); + printf("- %p - (%d ; %d) - (%d ; %d)\n", node, + alloc.x, alloc.y, + alloc.width, alloc.height); + + } + + if (state == GVS_ENTER) (*depth)++; + else if (state == GVS_EXIT) (*depth)--; + + return true; + + } + + printf("==== graph ====\n"); + g_graph_node_visit_nodes(result->nodes, (graph_node_visitor_cb)_print_dbg_ext_cb, (int []){ 0 }); + printf("\n"); + return result; } @@ -654,8 +706,10 @@ void g_graph_layout_refresh(GGraphLayout *layout) /* Traitement des positions horizontales */ - g_graph_node_set_position(layout->nodes, (gint []) { 0 }, NULL); - g_virtual_node_organize_x_line(G_VIRTUAL_NODE(layout->nodes), layout->nodes); + g_graph_node_set_x_position(layout->nodes, GRAPH_HORIZONTAL_MARGIN); + + g_graph_node_prepare_x_line(layout->nodes, layout->nodes); + g_graph_node_apply_position(layout->nodes); for (i = 0; i < layout->edges_count; i++) g_graph_edge_reserve_horizontal_space(layout->edges[i], layout->ranks); diff --git a/src/gtkext/graph/node-int.h b/src/gtkext/graph/node-int.h index dca4af5..b153255 100644 --- a/src/gtkext/graph/node-int.h +++ b/src/gtkext/graph/node-int.h @@ -33,19 +33,16 @@ typedef unsigned int (* get_node_rank_fc) (const GGraphNode *); /* Réinitialise la position d'un noeud d'encapsulation. */ -typedef void (* node_set_pos_fc) (GGraphNode *, gint *, gint *); - -/* Réinitialise la position d'un noeud d'encapsulation. */ typedef void (* node_reset_pos_fc) (GGraphNode *); -/* Altère la position du noeud d'encapsulation. */ -typedef void (* node_set_pos_fc) (GGraphNode *, gint *, gint *); +/* Définit les abscisses relatives du contenu d'un noeud. */ +typedef void (* node_prepare_x_fc) (GGraphNode *, GGraphNode *); -/* Fournit la position du noeud d'encapsulation. */ -typedef void (* node_get_pos_fc) (const GGraphNode *, gint *, gint *); +/* Applique une position finale au noeud. */ +typedef void (* node_apply_pos_fc) (GGraphNode *); -/* Indique l'espace requis pour un noeud d'encapsulation. */ -typedef GtkAllocation (* node_get_alloc_fc) (const GGraphNode *); +/* Altère la position du noeud d'encapsulation. */ +typedef void (* node_set_pos_fc) (GGraphNode *, gint); /* Parcourt tous les noeuds graphiques dans un ordre donné. */ typedef bool (* visit_flow_nodes_fc) (GGraphNode *, graph_node_visitor_cb, void *); @@ -61,9 +58,9 @@ struct _GGraphNode get_node_rank_fc get_rank; /* Premier rang d'appartenance */ node_reset_pos_fc reset_pos; /* Réinitialise l'emplacement */ + node_prepare_x_fc prepare_x; /* Préparation des abscisses */ + node_apply_pos_fc apply_pos; /* Applique une absisse finale */ node_set_pos_fc set_pos; /* Définit l'emplacement */ - node_get_pos_fc get_pos; /* Fournit l'emplacement */ - node_get_alloc_fc get_alloc; /* Fournit l'espace nécessaire */ visit_flow_nodes_fc visit; /* Visite des noeuds d'exécut° */ find_container_fc contain; /* Retrouve un conteneur */ @@ -71,8 +68,19 @@ struct _GGraphNode char name[NODE_NAME_LEN]; /* Adresse sous forme humaine */ GtkAllocation alloc; /* Emplacement du bloc rattaché*/ - gint pending_x; /* Décallage à appliquer #1 */ - gint pending_y; /* Décallage à appliquer #2 */ + pending_position pending_pos; /* Indication sur la position */ + PendingPositionFlags pending_flag; /* Cible le champ valide */ + GGraphNode *pending_rel; /* Eventuelle ref. relative */ + + + + gint pending_x; /* Décallage à appliquer #1 */ /* TODO : remme */ + gint pending_y; /* Décallage à appliquer #2 */ /* TODO : remme */ + + bool direct_x; /* Position strictement vert. */ + gint pending_left_margin; /* Limite à ne pas dépasser #1 */ + gint pending_right_margin; /* Limite à ne pas dépasser #2 */ + }; diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c index 47531e2..c79b8fc 100644 --- a/src/gtkext/graph/node.c +++ b/src/gtkext/graph/node.c @@ -144,6 +144,8 @@ static void g_graph_node_class_init(GGraphNodeClass *klass) static void g_graph_node_init(GGraphNode *node) { + node->alloc.x = UNINITIALIZED_NODE_POS; + node->alloc.y = UNINITIALIZED_NODE_POS; } @@ -253,7 +255,31 @@ unsigned int g_graph_node_get_rank(const GGraphNode *node) void g_graph_node_reset_position(GGraphNode *node) { - node->reset_pos(node); + node->alloc.x = UNINITIALIZED_NODE_POS; + node->alloc.y = UNINITIALIZED_NODE_POS; + + if (node->reset_pos != NULL) + node->reset_pos(node); + +} + + +/****************************************************************************** +* * +* Paramètres : node = noeud d'encapsulation à traiter. * +* nodes = ensemble des noeuds en place. * +* * +* Description : Définit les abscisses relatives du contenu d'un noeud. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_graph_node_prepare_x_line(GGraphNode *node, GGraphNode *nodes) +{ + node->prepare_x(node, nodes); } @@ -261,10 +287,8 @@ void g_graph_node_reset_position(GGraphNode *node) /****************************************************************************** * * * 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. * +* Description : Applique une position finale au noeud. * * * * Retour : - * * * @@ -272,22 +296,50 @@ void g_graph_node_reset_position(GGraphNode *node) * * ******************************************************************************/ -void g_graph_node_set_position(GGraphNode *node, gint *x, gint *y) +void g_graph_node_apply_position(GGraphNode *node) { -#if 1 - if (x != NULL && node->pending_x != 0) - { - *x += node->pending_x; - printf(" ((%p)) adding %d => %d\n", node, node->pending_x, *x); - node->pending_x = 0; - } - if (y != NULL && node->pending_y != 0) + gint x_pos; /* Position de référence */ + GGraphNode *ref; /* Accès rapide */ + + if (node->apply_pos != NULL) + node->apply_pos(node); + + switch (node->pending_flag) { - *y += node->pending_y; - node->pending_y = 0; + case PPF_DIRECT_X: + g_graph_node_get_position(node->pending_rel, &x_pos, NULL); + x_pos += node->pending_pos.direct_x; + g_graph_node_set_x_position(node, x_pos); + break; + + case PPF_LEFT_MARGIN: + g_graph_node_get_position(node->pending_rel, &x_pos, NULL); + x_pos += EDGE_SLOT_HORIZ_MARGIN + node->pending_pos.left_margin; + g_graph_node_set_x_position(node, x_pos); + break; + + case PPF_RIGHT_MARGIN: + g_graph_node_get_position(node->pending_rel, &x_pos, NULL); + x_pos += node->pending_pos.right_margin; + x_pos -= (EDGE_SLOT_HORIZ_MARGIN + node->alloc.width); + g_graph_node_set_x_position(node, x_pos); + break; + + case PPF_LEFT_NODE: + ref = node->pending_pos.left_node; + node->alloc.x = ref->alloc.x - NODE_HORIZONTAL_MARGIN - node->alloc.width; + break; + + case PPF_RIGHT_NODE: + ref = node->pending_pos.right_node; + node->alloc.x = ref->alloc.x + ref->alloc.width - NODE_HORIZONTAL_MARGIN; + break; + + default: + /* Position traitée par l'appelant */ + break; + } -#endif - node->set_pos(node, x, y); } @@ -295,8 +347,34 @@ void g_graph_node_set_position(GGraphNode *node, gint *x, gint *y) /****************************************************************************** * * * Paramètres : node = noeud graphique à manipuler. * -* x = éventuelle abscisse à intégrer ou NULL. * -* y = éventuelle ordonnée à intégrer ou NULL. * +* Paramètres : node = noeud graphique à manipuler. * +* x = abscisse à intégrer. * +* direct = indique un tracé direct éventuel. * +* * +* Description : Altère la position du noeud d'encapsulation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_graph_node_set_x_position(GGraphNode *node, gint x) +{ + if (node->set_pos != NULL && x != GRAPH_HORIZONTAL_MARGIN) + node->set_pos(node, x); + + node->alloc.x = x; + +} + + +/****************************************************************************** +* * +* Paramètres : node = noeud graphique à manipuler. * +* flag = nature de l'indication à intégrer. * +* pos = argument supplémentaire à venir chercher. * +* rel = éventuelle référence pour une relation relative. * * * * Description : Prépare la position du noeud pour l'alignement des liens. * * * @@ -306,33 +384,33 @@ void g_graph_node_set_position(GGraphNode *node, gint *x, gint *y) * * ******************************************************************************/ -void g_graph_node_set_pending_position(GGraphNode *node, gint *x, gint *y) +void g_graph_node_set_pending_position(GGraphNode *node, PendingPositionFlags flag, pending_position pos, GGraphNode *rel) { - gint cur_x; /* Abscisse courante */ - gint cur_y; /* Ordonnée courante */ - bool update_x; /* Mise à jour des abscisses */ - bool update_y; /* Mise à jour des ordonnées */ + node->pending_pos = pos; + node->pending_flag = flag; + node->pending_rel = rel; - g_graph_node_get_position(node, &cur_x, &cur_y); +} - if (x != NULL) - { - update_x = (cur_x != UNINITIALIZED_NODE_POS); - if (!update_x) node->pending_x += *x; - } - else update_x = false; - if (y != NULL) - { - update_y = (cur_y != UNINITIALIZED_NODE_POS); - if (!update_y) node->pending_y += *y; - } - else update_y = false; +/****************************************************************************** +* * +* Paramètres : node = noeud graphique à manipuler. * +* flag = nature de l'indication à intégrer. [OUT] * +* pos = argument supplémentaire à venir chercher. [OUT] * +* * +* Description : Indique la position du noeud pour l'alignement des liens. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - if (update_x || update_y) - g_graph_node_set_position(node, - update_x ? cur_x + *x : NULL, - update_y ? cur_x + *y : NULL); +void g_graph_node_get_pending_position(GGraphNode *node, PendingPositionFlags *flag, pending_position *pos) +{ + *pos = node->pending_pos; + *flag = node->pending_flag; } @@ -353,7 +431,8 @@ void g_graph_node_set_pending_position(GGraphNode *node, gint *x, gint *y) void g_graph_node_get_position(const GGraphNode *node, gint *x, gint *y) { - node->get_pos(node, x, y); + if (x != NULL) *x = node->alloc.x; + if (y != NULL) *y = node->alloc.y; } @@ -372,7 +451,7 @@ void g_graph_node_get_position(const GGraphNode *node, gint *x, gint *y) GtkAllocation g_graph_node_get_allocation(const GGraphNode *node) { - return node->get_alloc(node); + return node->alloc; } diff --git a/src/gtkext/graph/node.h b/src/gtkext/graph/node.h index fa2fa27..3346b00 100644 --- a/src/gtkext/graph/node.h +++ b/src/gtkext/graph/node.h @@ -59,6 +59,29 @@ typedef struct _GGraphNode GGraphNode; typedef struct _GGraphNodeClass GGraphNodeClass; +/* Indications sur l'abscisse idéale à adopter */ +typedef union _pending_position +{ + gint direct_x; /* Position strictement vert. */ + gint left_margin; /* Limite à ne pas dépasser #1 */ + gint right_margin; /* Limite à ne pas dépasser #2 */ + GGraphNode *left_node; /* Noeud de référence à droite */ + GGraphNode *right_node; /* Noeud de référence à gauche */ + +} pending_position; + +/* Définition présente dans les indications */ +typedef enum _PendingPositionFlags +{ + PPF_NONE, /* Aucune -> centrage */ + PPF_DIRECT_X, /* Position strictement vert. */ + PPF_LEFT_MARGIN, /* Limite à ne pas dépasser #1 */ + PPF_RIGHT_MARGIN, /* Limite à ne pas dépasser #2 */ + PPF_LEFT_NODE, /* Noeud de référence à droite */ + PPF_RIGHT_NODE /* Noeud de référence à gauche */ + +} PendingPositionFlags; + /* Détail sur une visite */ typedef enum _GNodeVisitState { @@ -86,11 +109,20 @@ unsigned int g_graph_node_get_rank(const GGraphNode *); /* Réinitialise la position d'un noeud de graphique. */ void g_graph_node_reset_position(GGraphNode *); +/* Définit les abscisses relatives du contenu d'un noeud. */ +void g_graph_node_prepare_x_line(GGraphNode *node, GGraphNode *nodes); + +/* Applique une position finale au noeud. */ +void g_graph_node_apply_position(GGraphNode *); + /* Altère la position du noeud d'encapsulation. */ -void g_graph_node_set_position(GGraphNode *, gint *, gint *); +void g_graph_node_set_x_position(GGraphNode *, gint); /* Prépare la position du noeud pour l'alignement des liens. */ -void g_graph_node_set_pending_position(GGraphNode *, gint *, gint *); +void g_graph_node_set_pending_position(GGraphNode *, PendingPositionFlags, pending_position, GGraphNode *); + +/* Indique la position du noeud pour l'alignement des liens. */ +void g_graph_node_get_pending_position(GGraphNode *, PendingPositionFlags *, pending_position *); /* Fournit la position du noeud d'encapsulation. */ void g_graph_node_get_position(const GGraphNode *, gint *, gint *); @@ -99,7 +131,7 @@ void g_graph_node_get_position(const GGraphNode *, gint *, gint *); ({ \ gint _x; \ g_graph_node_get_position(node, &_x, NULL); \ - _x != UNINITIALIZED_NODE_POS/* || node->pending_x != 0*/; \ + _x != UNINITIALIZED_NODE_POS; \ }) /* Espace constitué, entièrement ou non. */ 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); */ diff --git a/src/gtkext/graph/nodes/flow.h b/src/gtkext/graph/nodes/flow.h index 5c99284..5a6268e 100644 --- a/src/gtkext/graph/nodes/flow.h +++ b/src/gtkext/graph/nodes/flow.h @@ -70,9 +70,6 @@ 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 05a7063..48cc1fb 100644 --- a/src/gtkext/graph/nodes/virtual.c +++ b/src/gtkext/graph/nodes/virtual.c @@ -67,6 +67,16 @@ static void extend_vertical_links_spans(vert_links *, const reserved_vspan *); /* ---------------------- REPRESENTATIONS DES GROUPES LOGIQUES ---------------------- */ +/* Représentation d'un étage */ +typedef struct _virtual_level +{ + unsigned int rank; /* Rang associé à l'étage */ + + GGraphNode **children; /* Noeuds englobés */ + size_t count; /* Quantité de ces noeuds */ + +} virtual_level; + /* Encapsulation graphique d'un bloc virtuel (instance) */ struct _GVirtualNode { @@ -79,6 +89,8 @@ struct _GVirtualNode GGraphNode **children; /* Noeuds englobés */ size_t count; /* Quantité de ces noeuds */ + virtual_level *levels; /* Différents étages de noeuds */ + size_t lcount; /* Nombre de ces étages */ vert_links *left_padding; /* Espace à gauche pour liens */ vspan_slot_t left_count; /* Nombre de largeurs réservées*/ @@ -113,14 +125,20 @@ static unsigned int g_virtual_node_get_rank(const GVirtualNode *); /* Réinitialise la position d'un noeud d'encapsulation. */ static void g_virtual_node_reset_position(GVirtualNode *); -/* Altère la position du noeud d'encapsulation. */ -static void g_virtual_node_set_position(GVirtualNode *, gint *, gint *); +/* Définit les abscisses relatives du contenu d'un noeud. */ +static void g_virtual_node_prepare_x_line(GVirtualNode *, GGraphNode *); -/* Fournit la position du noeud d'encapsulation. */ -static void g_virtual_node_get_position(const GVirtualNode *, gint *, gint *); +/* Applique une position finale au noeud. */ +static void g_virtual_node_apply_position(GVirtualNode *); -/* Indique l'espace requis pour un noeud d'encapsulation. */ -static GtkAllocation g_virtual_node_get_allocation(const GVirtualNode *); +/* Définit les abscisses relatives du contenu d'un noeud. */ +static void g_virtual_node_apply_x_line(GVirtualNode *); + +/* Met à jour la largeur interne du noeud. */ +static void g_virtual_node_compute_width(GVirtualNode *); + +/* Altère la position du noeud d'encapsulation. */ +static void g_virtual_node_set_position(GVirtualNode *, gint); /* Parcourt tous les blocs d'instructions dans un ordre donné. */ static bool g_virtual_node_visit_flow_nodes(GVirtualNode *, graph_node_visitor_cb, void *); @@ -128,9 +146,6 @@ static bool g_virtual_node_visit_flow_nodes(GVirtualNode *, graph_node_visitor_c /* Recherche le noeud contenant un autre noeud. */ 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 *, GGraphNode *); - /* ---------------------------------------------------------------------------------- */ @@ -287,9 +302,9 @@ static void g_virtual_node_init(GVirtualNode *node) base->get_rank = (get_node_rank_fc)g_virtual_node_get_rank; base->reset_pos = (node_reset_pos_fc)g_virtual_node_reset_position; + base->prepare_x = (node_prepare_x_fc)g_virtual_node_prepare_x_line; + base->apply_pos = (node_apply_pos_fc)g_virtual_node_apply_position; base->set_pos = (node_set_pos_fc)g_virtual_node_set_position; - base->get_pos = (node_get_pos_fc)g_virtual_node_get_position; - base->get_alloc = (node_get_alloc_fc)g_virtual_node_get_allocation; base->visit = (visit_flow_nodes_fc)g_virtual_node_visit_flow_nodes; base->contain = (find_container_fc)g_virtual_node_find_container; @@ -410,19 +425,20 @@ static unsigned int g_virtual_node_get_rank(const GVirtualNode *node) static void g_virtual_node_reset_position(GVirtualNode *node) { - node->x = UNINITIALIZED_NODE_POS; - node->y = UNINITIALIZED_NODE_POS; + size_t i; /* Boucle de parcours */ + + for (i = 0; i < node->count; i++) + g_graph_node_reset_position(node->children[i]); } /****************************************************************************** * * -* Paramètres : node = noeud graphique à manipuler. * -* x = éventuelle abscisse à intégrer ou NULL. * -* y = éventuelle ordonnée à intégrer ou NULL. * +* Paramètres : node = noeud d'encapsulation à traiter. * +* nodes = ensemble des noeuds en place. * * * -* Description : Altère la position du noeud d'encapsulation. * +* Description : Définit les abscisses relatives du contenu d'un noeud. * * * * Retour : - * * * @@ -430,58 +446,167 @@ static void g_virtual_node_reset_position(GVirtualNode *node) * * ******************************************************************************/ -static void g_virtual_node_set_position(GVirtualNode *node, gint *x, gint *y) +static void g_virtual_node_prepare_x_line(GVirtualNode *node, GGraphNode *nodes) { - 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 */ + for (i = 0; i < node->count; i++) + g_graph_node_prepare_x_line(node->children[i], nodes); - //if (x != NULL) printf("-- setX -- %p -> %d (old=%d)\n", node, *x, node->x); +} - old_x = node->x; - old_y = node->y; +/****************************************************************************** +* * +* Paramètres : node = noeud d'encapsulation à traiter. * +* * +* Description : Applique une position finale au noeud. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - if (x != NULL) node->x = *x; - if (y != NULL) node->y = *y; +static void g_virtual_node_apply_position(GVirtualNode *node) +{ + gint min; /* Valeur minimale rencontrée */ + size_t i; /* Boucle de parcours */ + gint pos_x; /* Nouvelle position #1 */ + gint offset; /* Décallage à faire suivre */ - 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); + g_virtual_node_apply_x_line(node); - //printf("offx = %d\n", off_x); + /* Collecte de l'ensemble des positions */ + min = 0; for (i = 0; i < node->count; i++) { - g_graph_node_get_position(node->children[i], &pos_x, &pos_y); + g_graph_node_get_position(node->children[i], &pos_x, NULL); + min = MIN(min, pos_x); + } + /* Espace pour les liens remontants */ + if (node->left_count > 0) + offset = EDGE_SLOT_HORIZ_MARGIN + EDGE_HORIZONTAL_MIN_SEP * (node->left_count - 1); + else + offset = 0; + + /* Ajout du décallage le plus grand */ + offset += -min; - if (x != NULL) pos_x += off_x; + /* Traitement des sous-noeuds */ + for (i = 0; i < node->count; i++) + { + /* BUG_ON(node->children[i]->alloc.x != UNINITIALIZED_NODE_POS); */ - g_graph_node_set_position(node->children[i], &pos_x, &pos_y); + g_graph_node_get_position(node->children[i], &pos_x, NULL); + pos_x += offset; + g_graph_node_set_x_position(node->children[i], pos_x); } + g_virtual_node_compute_width(node); + +} + +/****************************************************************************** +* * +* Paramètres : node = noeud d'encapsulation à traiter. * +* * +* Description : Définit les abscisses relatives du contenu d'un noeud. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_virtual_node_apply_x_line(GVirtualNode *node) +{ + size_t i; /* Boucle de parcours #1 */ + virtual_level *level; /* Accès rapide */ + size_t j; /* Boucle de parcours #2 */ + gint width_sum; /* Largeur d'un étage traité */ + gint x_pos; /* Abscisse à attribuer */ + + for (i = 0; i < node->lcount; i++) + { + level = &node->levels[i]; + + /* Si l'ensemble de l'étage doit être aligné */ + if (level->children[0]->pending_flag == PPF_NONE) + { + width_sum = 0; + + for (j = 0; j < level->count; j++) + { + /* BUG_ON(level->children[j]->pending_flag != PPF_NONE); */ + + g_graph_node_apply_position(level->children[j]); + width_sum += level->children[j]->alloc.width; + + } + + width_sum += NODE_HORIZONTAL_MARGIN * (level->count - 1); + + x_pos = - width_sum / 2; + + for (j = 0; j < level->count; j++) + { + g_graph_node_set_x_position(level->children[j], x_pos); + x_pos += level->children[j]->alloc.width + NODE_HORIZONTAL_MARGIN; + } + + } + + /* On traite les noeuds individuellement */ + else + { + void _apply_rel_position(GGraphNode *child) + { + switch (node->children[0]->pending_flag) + { + case PPF_LEFT_NODE: + if (!g_graph_node_has_x_position(child->pending_pos.left_node)) + _apply_rel_position(child->pending_pos.left_node); + break; + + case PPF_RIGHT_NODE: + if (!g_graph_node_has_x_position(child->pending_pos.right_node)) + _apply_rel_position(child->pending_pos.right_node); + break; + + default: + break; + + } + + g_graph_node_apply_position(child); + + } + + for (j = 0; j < level->count; j++) + if (!g_graph_node_has_x_position(level->children[j])) + _apply_rel_position(level->children[j]); + + } + + } } /****************************************************************************** * * -* Paramètres : node = noeud graphique à consulter. * -* x = éventuelle abscisse à recevoir ou NULL. [OUT] * -* y = éventuelle ordonnée à recevoir ou NULL. [OUT] * +* Paramètres : node = noeud graphique à mettre à jour. * * * -* Description : Fournit la position du noeud d'encapsulation. * +* Description : Met à jour la largeur interne du noeud. * * * * Retour : - * * * @@ -489,10 +614,80 @@ static void g_virtual_node_set_position(GVirtualNode *node, gint *x, gint *y) * * ******************************************************************************/ -static void g_virtual_node_get_position(const GVirtualNode *node, gint *x, gint *y) +static void g_virtual_node_compute_width(GVirtualNode *node) { - if (x != NULL) *x = node->x; - if (y != NULL) *y = node->y; + GGraphNode *base; /* Accès rapides */ + size_t i; /* Boucle de parcours */ + GGraphNode *child; /* Raccourci confortable */ + + base = G_GRAPH_NODE(node); + + /* Largeur maximale des niveaux */ + + base->alloc.width = 0; + + for (i = 0; i < node->lcount; i++) + { + child = node->levels[i].children[node->levels[i].count - 1]; + + base->alloc.width = MAX(base->alloc.width, child->alloc.x + child->alloc.width); + + } + + /* Bordures gauche et droite */ + + if (node->left_count > 0) + { + base->alloc.width += EDGE_SLOT_HORIZ_MARGIN; + base->alloc.width += (node->left_count - 1) * EDGE_HORIZONTAL_MIN_SEP; + } + + if (node->right_count > 0) + { + base->alloc.width += EDGE_SLOT_HORIZ_MARGIN; + base->alloc.width += (node->right_count - 1) * EDGE_HORIZONTAL_MIN_SEP; + } + +} + + +/****************************************************************************** +* * +* Paramètres : node = noeud graphique à manipuler. * +* x = éventuelle abscisse à intégrer. * +* * +* Description : Altère la position du noeud d'encapsulation. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_virtual_node_set_position(GVirtualNode *node, gint x) +{ + GGraphNode *base; /* Autre version de l'instance */ + gint offset; /* Décallage à faire suivre */ + size_t i; /* Boucle de parcours */ + gint x_pos; /* Nouvelle position #1 */ + + base = G_GRAPH_NODE(node); + + if (base->alloc.x == UNINITIALIZED_NODE_POS) + offset = x; + else + offset = x - base->alloc.x; + + for (i = 0; i < node->count; i++) + { + /* BUG_ON(node->children[i]->alloc.x != UNINITIALIZED_NODE_POS); */ + + g_graph_node_get_position(node->children[i], &x_pos, NULL); + x_pos += offset; + + g_graph_node_set_x_position(node->children[i], x_pos); + + } } @@ -669,6 +864,12 @@ static GGraphNode *g_virtual_node_find_container(GVirtualNode *node, GGraphNode void g_virtual_node_add_child(GVirtualNode *node, GGraphNode *child) { + unsigned int rank; /* Rang de l'enfant */ + virtual_level *level; /* Niveau d'intégration */ + size_t i; /* Boucle de parcours */ + + /* Liste globale */ + node->children = (GGraphNode **)realloc(node->children, ++node->count * sizeof(GGraphNode *)); @@ -676,6 +877,33 @@ void g_virtual_node_add_child(GVirtualNode *node, GGraphNode *child) g_object_ref(G_OBJECT(child)); + /* Intégration dans l'étage correspondant */ + + rank = g_graph_node_get_rank(child); + + level = NULL; + + for (i = 0; i < node->lcount && level == NULL; i++) + if (node->levels[i].rank == rank) + level = &node->levels[i]; + + if (level == NULL) + { + node->levels = (virtual_level *)realloc(node->levels, + ++node->lcount * sizeof(virtual_level)); + level = &node->levels[node->lcount - 1]; + + level->rank = rank; + level->children = NULL; + level->count = 0; + + } + + level->children = (GGraphNode **)realloc(level->children, + ++level->count * sizeof(GGraphNode *)); + + level->children[level->count - 1] = child; + } @@ -777,174 +1005,6 @@ vspan_slot_t g_virtual_node_reserve_span(GVirtualNode *node, unsigned int r1, un /****************************************************************************** * * -* 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_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, nodes); - - min = 0; - - for (i = 0; i < node->count; i++) - { - g_graph_node_get_position(node->children[i], &x, NULL); - min = MIN(min, x); - } - - node->x += GRAPH_HORIZONTAL_MARGIN; - min = -min + GRAPH_HORIZONTAL_MARGIN; - - g_virtual_node_offset_x_line(node, min); - -} - - -/****************************************************************************** -* * -* Paramètres : node = noeud d'encapsulation à traiter. * -* nodes = ensemble des noeuds en place. * -* * -* Description : Définit les abscisses relatives du contenu d'un noeud. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -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 */ - size_t i; /* Boucle de parcours */ - GGraphNode *child; /* Raccourci confortable */ - gint last_pos; /* Dernière position */ - GtkAllocation alloc; /* Espace pour l'affichage */ - - /* Si le rang d'entrée contient tous les éléments... */ - if (node->count > 1) - { - rank_0 = g_graph_node_get_rank(node->children[0]); - rank_1 = g_graph_node_get_rank(node->children[1]); - - if (rank_0 == rank_1) - { - g_graph_node_set_position(node->children[0], (gint []) { 0/*-(alloc.width / 2)*/ }, NULL); - - for (i = 1; i < node->count; i++) - { - /* Récupération de la position précédente */ - - child = node->children[i - 1]; - - g_graph_node_get_position(child, &last_pos, NULL); - alloc = g_graph_node_get_allocation(child); - - last_pos += alloc.width + NODE_LEFT_MARGIN; - - /* Application sur le noeud courant */ - - child = node->children[i]; - - alloc = g_graph_node_get_allocation(child); - - g_graph_node_set_position(child, &last_pos, NULL); - - } - - } - - } - - for (i = 0; i < node->count; i++) - { - child = node->children[i]; - - /* Emplacement du fils */ - - if (!g_graph_node_has_x_position(child)) - { - alloc = g_graph_node_get_allocation(child); - g_graph_node_set_position(child, (gint []) { -(alloc.width / 2) }, NULL); - } - - /* 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), nodes); - - /*else BUG_ON(1); */ - - } - -} - - -/****************************************************************************** -* * -* Paramètres : node = noeud d'encapsulation à traiter. * -* xoffset = valeur du décallage. * -* * -* Description : Procède à un décallage du contenu sur l'axe des abscisses. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_virtual_node_offset_x_line(GVirtualNode *node, gint xoffset) -{ - gint padding; /* Décallage supplémentaire */ - size_t i; /* Boucle de parcours */ - gint x; /* Position d'un sous-noeud */ - GGraphNode *child; /* Raccourci confortable */ - - /* Espace pour les liens remontants */ - - if (node->left_count > 0) - padding = EDGE_SLOT_HORIZ_MARGIN + EDGE_HORIZONTAL_MIN_SEP * (node->left_count - 1); - else - padding = 0; - - /* Traitement de sous-noeuds */ - - for (i = 0; i < node->count; i++) - { - child = node->children[i]; - - g_graph_node_get_position(child, &x, NULL); - - 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); - - } - -} - - -/****************************************************************************** -* * * Paramètres : node = conteneur de noeuds à consulter. * * slot = numérod de la réservation. * * left = désignation de la zone à traiter. * diff --git a/src/gtkext/graph/nodes/virtual.h b/src/gtkext/graph/nodes/virtual.h index a7a96d7..77e4a63 100644 --- a/src/gtkext/graph/nodes/virtual.h +++ b/src/gtkext/graph/nodes/virtual.h @@ -68,12 +68,6 @@ GGraphNode *g_virtual_node_get_child(const GVirtualNode *, size_t); /* Réserve une portion de largeur pour un lien. */ 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 *, GGraphNode *); - -/* Procède à un décallage du contenu sur l'axe des abscisses. */ -void g_virtual_node_offset_x_line(GVirtualNode *, gint); - /* Fournit la position horizontale obtenue par réservation. */ gint g_virtual_node_get_x_for_vspan_slot(const GVirtualNode *, vspan_slot_t, bool); diff --git a/src/gtkext/graph/params.h b/src/gtkext/graph/params.h index d4fea24..a1e5452 100644 --- a/src/gtkext/graph/params.h +++ b/src/gtkext/graph/params.h @@ -55,9 +55,6 @@ -/* Séparation verticale minimale entre deux noeuds */ -#define NODE_VERTICAL_MARGIN 35 - @@ -69,6 +66,9 @@ #define EDGE_SLOT_HORIZ_MARGIN 20 #define EDGE_SLOT_VERT_MARGIN 20 +/* Séparations minimales entre un noeud et un autre */ +#define NODE_HORIZONTAL_MARGIN 20 +#define NODE_VERTICAL_MARGIN 35 |