From 4605b4ac4a04bb11bdf91d77e248656702774bde Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 12 May 2015 18:55:55 +0000
Subject: Ensured parent nodes are centered on their children when expected.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@534 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                        | 16 ++++++++++++++++
 src/gtkext/graph/layout.c        |  4 ++--
 src/gtkext/graph/node-int.h      |  7 +------
 src/gtkext/graph/node.c          | 24 ++++++++++++------------
 src/gtkext/graph/node.h          | 28 +++++++++++++++++++++-------
 src/gtkext/graph/nodes/flow.c    | 28 +++++++++++++++++++++++-----
 src/gtkext/graph/nodes/virtual.c | 34 ++++++++++++++++++++++++++++++++++
 7 files changed, 109 insertions(+), 32 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 22cd68e..71a2009 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+15-05-12  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/gtkext/graph/layout.c:
+	Fix compilation warnings.
+
+	* src/gtkext/graph/node.c:
+	* src/gtkext/graph/node.h:
+	Introduce a new kink of pending position.
+
+	* src/gtkext/graph/node-int.h:
+	Clean and update the code.
+
+	* src/gtkext/graph/nodes/flow.c:
+	* src/gtkext/graph/nodes/virtual.c:
+	Ensure parent nodes are centered on their children when expected.
+
 15-05-11  Cyrille Bagard <nocbos@gmail.com>
 
 	* configure.ac;
diff --git a/src/gtkext/graph/layout.c b/src/gtkext/graph/layout.c
index 1084578..13f6270 100644
--- a/src/gtkext/graph/layout.c
+++ b/src/gtkext/graph/layout.c
@@ -248,7 +248,7 @@ GGraphLayout *g_graph_layout_new(GInstrBlock *blocks, GtkBufferView **views, siz
             for (i = 0; i < *depth; i++)
                 printf("   ");
 
-            g_graph_node_get_pending_position(node, &pending_flag, (pending_position []) { { 0 } });
+            g_graph_node_get_pending_position(node, &pending_flag, NULL);
             flags = flags_list[pending_flag];
 
             alloc = g_graph_node_get_allocation(node);
@@ -261,7 +261,7 @@ GGraphLayout *g_graph_layout_new(GInstrBlock *blocks, GtkBufferView **views, siz
             {
                 printf("  - rank = %u  -", g_graph_node_get_rank(node));
 
-                g_flow_block_get_boundary(g_flow_node_get_block(node), &first, &last);
+                g_flow_block_get_boundary(g_flow_node_get_block(G_FLOW_NODE(node)), &first, &last);
                 printf("  - 0x%08x <-> 0x%08x", first->range.addr.virtual, last->range.addr.virtual);
             }
 
diff --git a/src/gtkext/graph/node-int.h b/src/gtkext/graph/node-int.h
index 2572fce..c052e0d 100644
--- a/src/gtkext/graph/node-int.h
+++ b/src/gtkext/graph/node-int.h
@@ -57,13 +57,8 @@ struct _GGraphNode
     GObject parent;                         /* A laisser en premier        */
 
     GtkAllocation alloc;                    /* Emplacement du bloc rattaché*/
-    pending_position pending_pos;           /* Indication sur la position  */
     PendingPositionFlags pending_flag;      /* Cible le champ valide       */
-    GGraphNode *pending_rel;                /* Eventuelle ref. relative    */
-
-    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 */
+    pending_position pending_pos;           /* Indication sur la position  */
 
 };
 
diff --git a/src/gtkext/graph/node.c b/src/gtkext/graph/node.c
index 0210aa3..08dd970 100644
--- a/src/gtkext/graph/node.c
+++ b/src/gtkext/graph/node.c
@@ -232,22 +232,22 @@ void g_graph_node_apply_position(GGraphNode *node)
     switch (node->pending_flag)
     {
         case PPF_DIRECT_X:
-            assert(g_graph_node_has_x_position(node->pending_rel));
-            g_graph_node_get_position(node->pending_rel, &x_pos, NULL);
+            assert(g_graph_node_has_x_position(node->pending_pos.relative_ref));
+            g_graph_node_get_position(node->pending_pos.relative_ref, &x_pos, NULL);
             x_pos += node->pending_pos.direct_x;
             g_graph_node_set_x_position(node, x_pos);
             break;
 
         case PPF_LEFT_MARGIN:
-            assert(g_graph_node_has_x_position(node->pending_rel));
-            g_graph_node_get_position(node->pending_rel, &x_pos, NULL);
+            assert(g_graph_node_has_x_position(node->pending_pos.relative_ref));
+            g_graph_node_get_position(node->pending_pos.relative_ref, &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:
-            assert(g_graph_node_has_x_position(node->pending_rel));
-            g_graph_node_get_position(node->pending_rel, &x_pos, NULL);
+            assert(g_graph_node_has_x_position(node->pending_pos.relative_ref));
+            g_graph_node_get_position(node->pending_pos.relative_ref, &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);
@@ -304,7 +304,6 @@ void g_graph_node_set_x_position(GGraphNode *node, gint 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.    *
 *                                                                             *
@@ -314,14 +313,13 @@ void g_graph_node_set_x_position(GGraphNode *node, gint x)
 *                                                                             *
 ******************************************************************************/
 
-void g_graph_node_set_pending_position(GGraphNode *node, PendingPositionFlags flag, pending_position pos, GGraphNode *rel)
+void g_graph_node_set_pending_position(GGraphNode *node, PendingPositionFlags flag, pending_position pos)
 {
-    if (node->pending_flag != PPF_NONE)
+    if (node->pending_flag != PPF_NONE && node->pending_flag != PPF_MIDDLE_OF)
         return;
 
-    node->pending_pos = pos;
     node->pending_flag = flag;
-    node->pending_rel = rel;
+    node->pending_pos = pos;
 
 }
 
@@ -342,9 +340,11 @@ void g_graph_node_set_pending_position(GGraphNode *node, PendingPositionFlags fl
 
 void g_graph_node_get_pending_position(GGraphNode *node, PendingPositionFlags *flag, pending_position *pos)
 {
-    *pos = node->pending_pos;
     *flag = node->pending_flag;
 
+    if (pos != NULL)
+        *pos = node->pending_pos;
+
 }
 
 
diff --git a/src/gtkext/graph/node.h b/src/gtkext/graph/node.h
index 502b366..6d3589a 100644
--- a/src/gtkext/graph/node.h
+++ b/src/gtkext/graph/node.h
@@ -55,11 +55,24 @@ 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 */
+    /* PPF_DIRECT_X, PPF_LEFT_MARGIN, PPF_RIGHT_MARGIN */
+    struct
+    {
+        union
+        {
+            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 *relative_ref;           /* Eventuelle ref. relative    */
+    };
+
+    /* PPF_LEFT_NODE, PPF_RIGHT_NODE, PPF_MIDDLE_OF */
+    struct
+    {
+        GGraphNode *left_node;              /* Noeud de référence à droite */
+        GGraphNode *right_node;             /* Noeud de référence à gauche */
+    };
 
 } pending_position;
 
@@ -71,7 +84,8 @@ typedef enum _PendingPositionFlags
     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 */
+    PPF_RIGHT_NODE,                         /* Noeud de référence à gauche */
+    PPF_MIDDLE_OF                           /* Centré entre deux noeuds    */
 
 } PendingPositionFlags;
 
@@ -107,7 +121,7 @@ void g_graph_node_apply_position(GGraphNode *);
 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 *, PendingPositionFlags, pending_position, GGraphNode *);
+void g_graph_node_set_pending_position(GGraphNode *, PendingPositionFlags, pending_position);
 
 /* Indique la position du noeud pour l'alignement des liens. */
 void g_graph_node_get_pending_position(GGraphNode *, PendingPositionFlags *, pending_position *);
diff --git a/src/gtkext/graph/nodes/flow.c b/src/gtkext/graph/nodes/flow.c
index ca5dceb..2f822bd 100644
--- a/src/gtkext/graph/nodes/flow.c
+++ b/src/gtkext/graph/nodes/flow.c
@@ -351,6 +351,8 @@ static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
 
             pos.direct_x -= (G_GRAPH_NODE(target)->alloc.width - G_GRAPH_NODE(node)->alloc.width) / 2;
 
+            pos.relative_ref = base;
+
             size_t count_and_skip_loop(GFlowNode *n)
             {
                 size_t counter;
@@ -364,7 +366,7 @@ static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
             }
 
             if (count_and_skip_loop(target) == 1)
-                g_graph_node_set_pending_position(G_GRAPH_NODE(target), PPF_DIRECT_X, pos, base);
+                g_graph_node_set_pending_position(G_GRAPH_NODE(target), PPF_DIRECT_X, pos);
 
             break;
 
@@ -377,8 +379,18 @@ static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
             rank_b = g_flow_node_get_rank(target_b);
 
             if (rank_a == rank_b)
+            {
+                /* On s'assure que le père est centré par rapport aux deux fils */
+
+                pos.left_node = G_GRAPH_NODE(target_a);
+                pos.right_node = G_GRAPH_NODE(target_b);
+
+                g_graph_node_set_pending_position(base, PPF_MIDDLE_OF, pos);
+
                 break;
 
+            }
+
             /* Alignement d'un bloc lié */
 
             if (rank_a > rank_b)
@@ -392,7 +404,8 @@ static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
                 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);
+                pos.relative_ref = base;
+                g_graph_node_set_pending_position(container, PPF_LEFT_MARGIN, pos);
 
                 /* Trait vertical de l'autre côté... */
 
@@ -403,7 +416,9 @@ static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
 
                 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);
+                pos.relative_ref = base;
+
+                g_graph_node_set_pending_position(G_GRAPH_NODE(target_a), PPF_DIRECT_X, pos);
 
             }
             else
@@ -417,7 +432,8 @@ static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
                 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);
+                pos.relative_ref = base;
+                g_graph_node_set_pending_position(container, PPF_RIGHT_MARGIN, pos);
 
                 /* Trait vertical de l'autre côté... */
 
@@ -428,7 +444,9 @@ static void g_flow_node_prepare_x_line(GFlowNode *node, GGraphNode *nodes)
 
                 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);
+                pos.relative_ref = base;
+
+                g_graph_node_set_pending_position(G_GRAPH_NODE(target_b), PPF_DIRECT_X, pos);
 
             }
 
diff --git a/src/gtkext/graph/nodes/virtual.c b/src/gtkext/graph/nodes/virtual.c
index 894c6b6..62f5b42 100644
--- a/src/gtkext/graph/nodes/virtual.c
+++ b/src/gtkext/graph/nodes/virtual.c
@@ -528,6 +528,8 @@ static void g_virtual_node_apply_x_line(GVirtualNode *node)
     size_t j;                               /* Boucle de parcours #2       */
     gint width_sum;                         /* Largeur d'un étage traité   */
     gint x_pos;                             /* Abscisse à attribuer        */
+    GGraphNode *ref_a;                      /* Accès rapide #1             */
+    GGraphNode *ref_b;                      /* Accès rapide #2             */
 
     for (i = 0; i < node->lcount; i++)
     {
@@ -559,6 +561,9 @@ static void g_virtual_node_apply_x_line(GVirtualNode *node)
 
         }
 
+        else if (level->children[0]->pending_flag == PPF_MIDDLE_OF)
+            continue;
+
         /* On traite les noeuds individuellement */
         else
         {
@@ -593,6 +598,35 @@ static void g_virtual_node_apply_x_line(GVirtualNode *node)
 
     }
 
+    for (i = 0; i < node->lcount; i++)
+    {
+        level = &node->levels[i];
+
+        /* Si l'ensemble de l'étage doit être centré */
+        if (level->children[0]->pending_flag == PPF_MIDDLE_OF)
+        {
+            ref_a = level->children[0]->pending_pos.left_node;
+            ref_b = level->children[0]->pending_pos.right_node;
+
+            assert(g_graph_node_has_x_position(ref_a));
+            assert(g_graph_node_has_x_position(ref_b));
+
+            if (ref_a->alloc.x < ref_b->alloc.x)
+            {
+                ref_b = level->children[0]->pending_pos.left_node;
+                ref_a = level->children[0]->pending_pos.right_node;
+            }
+
+            x_pos = ref_a->alloc.x;
+            x_pos += (ref_b->alloc.x + ref_b->alloc.width - ref_a->alloc.x) / 2;
+            x_pos -= level->children[0]->alloc.width / 2;
+
+            g_graph_node_set_x_position(level->children[0], x_pos);
+
+        }
+
+    }
+
 }
 
 
-- 
cgit v0.11.2-87-g4458