From 427f80181b1d839bf97d9a7caec88f81bf961e25 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 23 Feb 2019 01:55:50 +0100 Subject: Limited the length of some loop links in the graph view. --- src/gtkext/graph/cluster.c | 216 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 163 insertions(+), 53 deletions(-) diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c index 51d73c7..4f39b28 100644 --- a/src/gtkext/graph/cluster.c +++ b/src/gtkext/graph/cluster.c @@ -108,6 +108,8 @@ typedef struct _vspace_booking_t GdkPoint *pts; /* Coordonnées des points */ + bool external; /* Lien vers un cluster parent */ + } vspace_booking_t; /* Réservations d'espaces latéraux */ @@ -132,10 +134,10 @@ static void init_vspace_manager(vspace_manager_t *); static void exit_vspace_manager(vspace_manager_t *); /* Inscrit une nouvelle réservation d'espace latéral. */ -static void extend_vspace_manager(vspace_manager_t *, leaving_link_t *, incoming_link_t *, GdkPoint *); +static void extend_vspace_manager(vspace_manager_t *, leaving_link_t *, incoming_link_t *, GdkPoint *, bool); /* Détermine l'emplacement requis pour les espaces latéraux. */ -static void compute_vspace_manager_needed_alloc(const vspace_manager_t *, GtkAllocation *); +static void compute_vspace_manager_needed_alloc(const vspace_manager_t *, bool, GtkAllocation *); /* Réorganise au besoin les liens de boucle entre blocs. */ static void sort_incoming_links_for_vspace_manager(vspace_manager_t *); @@ -144,7 +146,7 @@ static void sort_incoming_links_for_vspace_manager(vspace_manager_t *); static void offset_x_vspace_manager(vspace_manager_t *, gint); /* Détermine les abscisses de tous les liens en place. */ -static gint compute_loop_link_x_with_vspace_manager(const vspace_manager_t *, const GtkAllocation *); +static gint compute_loop_link_x_with_vspace_manager(const vspace_manager_t *, const GtkAllocation *, bool); /* Détermine les ordonnées de tous les liens en place. */ static void compute_loop_link_y_with_vspace_manager(const vspace_manager_t *, const GtkAllocation *); @@ -211,8 +213,11 @@ static int cmp_graph_rank(const graph_rank_t *, const graph_rank_t *); /* Etend un ensemble de blocs de même rang. */ static void extend_graph_rank(graph_rank_t *, GGraphCluster *); +/* Détermine si un groupe de blocs contient un bloc particulier. */ +static bool has_graph_rank_cluster(const graph_rank_t *, GGraphCluster *); + /* Inscrit à l'endroit idéal une réservation d'espace latéral. */ -static bool extend_graph_rank_vspace_manager(graph_rank_t *, leaving_link_t *, incoming_link_t *, GdkPoint *); +static bool extend_graph_rank_vspace_manager(graph_rank_t *, leaving_link_t *, incoming_link_t *, GdkPoint *, bool); /* Détermine l'emplacement requis d'un ensemble de blocs. */ static void compute_graph_rank_needed_alloc(const graph_rank_t *, bool, GtkAllocation *); @@ -275,7 +280,7 @@ struct _GGraphCluster graph_rank_t *ranks; /* Répartition verticale */ size_t ranks_count; /* Nombre de divisions */ - vspace_manager_t vspaces; /* Gestion des liens latéraux */ + vspace_manager_t self; /* Gestion d'un retour direct */ }; @@ -675,10 +680,11 @@ static void exit_vspace_manager(vspace_manager_t *manager) /****************************************************************************** * * -* Paramètres : manager = structure à compléter. * -* from = point de départ du lien concerné. * -* to = point d'arrivée du lien concerné. * -* pts = points intermédiaires du tracé complet final. * +* Paramètres : manager = structure à compléter. * +* from = point de départ du lien concerné. * +* to = point d'arrivée du lien concerné. * +* pts = points intermédiaires du tracé complet final. * +* external = précise une sortie du cadre du cluster premier. * * * * Description : Inscrit une nouvelle réservation d'espace latéral. * * * @@ -688,7 +694,7 @@ static void exit_vspace_manager(vspace_manager_t *manager) * * ******************************************************************************/ -static void extend_vspace_manager(vspace_manager_t *manager, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts) +static void extend_vspace_manager(vspace_manager_t *manager, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts, bool external) { vspace_booking_t *new; /* Réservation à constituer */ @@ -701,13 +707,16 @@ static void extend_vspace_manager(vspace_manager_t *manager, leaving_link_t *fro new->pts = pts; + new->external = external; + } /****************************************************************************** * * -* Paramètres : manager = gestion des espaces latéraux à consulter. * -* alloc = emplacement idéal pour l'affichage. [OUT] * +* Paramètres : manager = gestion des espaces latéraux à consulter. * +* external = précise une sortie du cadre du cluster premier. * +* alloc = emplacement idéal pour l'affichage. [OUT] * * * * Description : Détermine l'emplacement requis pour les espaces latéraux. * * * @@ -717,25 +726,42 @@ static void extend_vspace_manager(vspace_manager_t *manager, leaving_link_t *fro * * ******************************************************************************/ -static void compute_vspace_manager_needed_alloc(const vspace_manager_t *manager, GtkAllocation *alloc) +static void compute_vspace_manager_needed_alloc(const vspace_manager_t *manager, bool external, GtkAllocation *alloc) { gint width; /* Largeur supplémentaire */ - - /* Extension de la largeur */ + size_t count; /* Nombre de liens retenus */ + size_t i; /* Boucle de parcours */ width = 0; - width += manager->left_count * LINK_MARGIN; + /* Extension de la largeur, à gauche */ + + count = 0; + + for (i = 0; i < manager->left_count; i++) + if (manager->left[i]->external == external) + count++; + + width += count * LINK_MARGIN; alloc->x -= width; - width += manager->right_count * LINK_MARGIN; + /* Extension de la largeur, à droite */ + + count = 0; + + for (i = 0; i < manager->right_count; i++) + if (manager->right[i]->external == external) + count++; + + width += count * LINK_MARGIN; alloc->width += width; /* Extension de la hauteur */ - alloc->height += manager->pending_count * VERTICAL_MARGIN; + if (!external) + alloc->height += manager->pending_count * VERTICAL_MARGIN; } @@ -836,8 +862,9 @@ static void offset_x_vspace_manager(vspace_manager_t *manager, gint offset) /****************************************************************************** * * -* Paramètres : manager = structure à consulter. * -* needed = espace nécessaire et alloué pour les blocs. * +* Paramètres : manager = structure à consulter. * +* needed = espace nécessaire et alloué pour les blocs. * +* external = précise une sortie du cadre du cluster premier. * * * * Description : Détermine les abscisses de tous les liens en place. * * * @@ -847,37 +874,42 @@ static void offset_x_vspace_manager(vspace_manager_t *manager, gint offset) * * ******************************************************************************/ -static gint compute_loop_link_x_with_vspace_manager(const vspace_manager_t *manager, const GtkAllocation *needed) +static gint compute_loop_link_x_with_vspace_manager(const vspace_manager_t *manager, const GtkAllocation *needed, bool external) { gint result; /* Eventuelle marge à renvoyer */ + size_t count; /* Quantité de liens traités */ size_t i; /* Boucle de parcours */ vspace_booking_t *booking; /* Réservation à traiter */ gint x; /* Position à appliquer */ + count = 0; + for (i = 0; i < manager->left_count; i++) { booking = manager->left[i]; - x = (i + 1) * LINK_MARGIN; + x = ++count * LINK_MARGIN; booking->pts[0].x = needed->x - x; booking->pts[1].x = needed->x - x; } + result = count * LINK_MARGIN; + + count = 0; + for (i = 0; i < manager->right_count; i++) { booking = manager->right[i]; - x = (i + 1) * LINK_MARGIN; + x = ++count * LINK_MARGIN; booking->pts[0].x = needed->x + needed->width + x; booking->pts[1].x = needed->x + needed->width + x; } - result = manager->left_count * LINK_MARGIN; - return result; } @@ -1199,20 +1231,18 @@ static void extend_graph_rank(graph_rank_t *grank, GGraphCluster *cluster) /****************************************************************************** * * -* Paramètres : grank = ensemble de descendants d'un même rang. * -* from = point de départ du lien concerné. * -* to = point d'arrivée du lien concerné. * -* pts = points intermédiaires du tracé complet final. * +* Paramètres : grank = structure à compléter. * +* cluster = chef de file d'un ensemble de blocs. * * * -* Description : Inscrit à l'endroit idéal une réservation d'espace latéral. * +* Description : Détermine si un groupe de blocs contient un bloc particulier.* * * -* Retour : true si la demande a bien été traitée. * +* Retour : true si le chef est bien contenu, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -static bool extend_graph_rank_vspace_manager(graph_rank_t *grank, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts) +static bool has_graph_rank_cluster(const graph_rank_t *grank, GGraphCluster *cluster) { bool result; /* Bilan à renvoyer */ size_t i; /* Boucle de parcours */ @@ -1220,10 +1250,37 @@ static bool extend_graph_rank_vspace_manager(graph_rank_t *grank, leaving_link_t result = false; for (i = 0; i < grank->count && !result; i++) - result = (grank->clusters[i] == from->owner); + result = (grank->clusters[i] == cluster); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : grank = ensemble de descendants d'un même rang. * +* from = point de départ du lien concerné. * +* to = point d'arrivée du lien concerné. * +* pts = points intermédiaires du tracé complet final. * +* external = précise une sortie du cadre du cluster premier. * +* * +* Description : Inscrit à l'endroit idéal une réservation d'espace latéral. * +* * +* Retour : true si la demande a bien été traitée. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool extend_graph_rank_vspace_manager(graph_rank_t *grank, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts, bool external) +{ + bool result; /* Bilan à renvoyer */ + + result = has_graph_rank_cluster(grank, from->owner); if (result) - extend_vspace_manager(&grank->vspaces, from, to, pts); + extend_vspace_manager(&grank->vspaces, from, to, pts, external); return result; @@ -1307,7 +1364,7 @@ static void compute_graph_rank_needed_alloc(const graph_rank_t *grank, bool last } - compute_vspace_manager_needed_alloc(&grank->vspaces, alloc); + compute_vspace_manager_needed_alloc(&grank->vspaces, false, alloc); } @@ -1459,7 +1516,7 @@ static void offset_x_graph_rank(graph_rank_t *grank, gint offset) /****************************************************************************** * * * Paramètres : grank = ensemble de blocs de même rang à actualiser. * -* needed = espace nécessaire et alloué pour les blocs. * +* needed = espace nécessaire et alloué pour les blocs. * * * * Description : Détermine les abscisses des liens de boucle en place. * * * @@ -1477,7 +1534,7 @@ static gint compute_loop_link_x_positions_with_graph_rank(const graph_rank_t *gr for (i = 0; i < grank->count; i++) g_graph_cluster_compute_loop_link_x_positions(grank->clusters[i]); - result = compute_loop_link_x_with_vspace_manager(&grank->vspaces, needed); + result = compute_loop_link_x_with_vspace_manager(&grank->vspaces, needed, false); return result; @@ -1619,7 +1676,7 @@ static void g_graph_cluster_class_init(GGraphClusterClass *klass) static void g_graph_cluster_init(GGraphCluster *cluster) { - init_vspace_manager(&cluster->vspaces); + init_vspace_manager(&cluster->self); } @@ -1680,7 +1737,7 @@ static void g_graph_cluster_finalize(GGraphCluster *cluster) if (cluster->ranks != NULL) free(cluster->ranks); - exit_vspace_manager(&cluster->vspaces); + exit_vspace_manager(&cluster->self); G_OBJECT_CLASS(g_graph_cluster_parent_class)->finalize(G_OBJECT(cluster)); @@ -1867,17 +1924,28 @@ static void g_graph_cluster_setup_link_for_target(GGraphCluster *source, GGraphC static void g_graph_cluster_extend_vspace_manager(GGraphCluster *target, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts) { bool done; /* Bilan des traitements */ + GGraphCluster *container; /* Arrivée de boucle extérieure*/ size_t i; /* Boucle de parcours */ assert(target == to->owner); done = false; - for (i = 0; i < target->ranks_count && !done; i++) - done = extend_graph_rank_vspace_manager(&target->ranks[i], from, to, pts); + if (from->owner == target) + extend_vspace_manager(&target->self, from, to, pts, false); + + else + { + for (i = 0; i < target->ranks_count && !done; i++) + done = extend_graph_rank_vspace_manager(&target->ranks[i], from, to, pts, false); + + container = from->owner->owner; + assert(container != NULL); - if (!done) - extend_vspace_manager(&target->vspaces, from, to, pts); + for (i = 0; i < container->ranks_count && !done; i++) + done = extend_graph_rank_vspace_manager(&container->ranks[i], from, to, pts, true); + + } } @@ -2193,7 +2261,7 @@ static void g_graph_cluster_sort_incoming_links(GGraphCluster *cluster) for (i = 0; i < cluster->ranks_count; i++) sort_graph_rank_incoming_links(&cluster->ranks[i]); - sort_incoming_links_for_vspace_manager(&cluster->vspaces); + sort_incoming_links_for_vspace_manager(&cluster->self); } @@ -2248,7 +2316,7 @@ static void g_graph_cluster_offset_x(GGraphCluster *cluster, gint offset) for (i = 0; i < cluster->ranks_count; i++) offset_x_graph_rank(&cluster->ranks[i], offset); - offset_x_vspace_manager(&cluster->vspaces, offset); + offset_x_vspace_manager(&cluster->self, offset); } @@ -2295,14 +2363,34 @@ static void g_graph_cluster_set_y(GGraphCluster *cluster, gint base) void g_graph_cluster_compute_needed_alloc(const GGraphCluster *cluster, GtkAllocation *alloc) { - size_t i; /* Boucle de parcours */ + size_t i; /* Boucle de parcours #1 */ + GGraphCluster *start; /* Départ de boucle extérieure */ + GGraphCluster *container; /* Arrivée de boucle extérieure*/ + size_t k; /* Boucle de parcours #2 */ *alloc = cluster->alloc; for (i = 0; i < cluster->ranks_count; i++) compute_graph_rank_needed_alloc(&cluster->ranks[i], (i + 1) == cluster->ranks_count, alloc); - compute_vspace_manager_needed_alloc(&cluster->vspaces, alloc); + for (i = 0; i < cluster->ta_count; i++) + if (cluster->top_anchors[i]->type == ILT_LOOP) + { + start = cluster->top_anchors[i]->other->owner; + + container = start->owner; + assert(container != NULL); + + for (k = 0; k < container->ranks_count; k++) + if (has_graph_rank_cluster(&container->ranks[k], start)) + { + compute_vspace_manager_needed_alloc(&container->ranks[k].vspaces, true, alloc); + break; + } + + assert(k < container->ranks_count); + + } } @@ -2549,7 +2637,10 @@ static void g_graph_cluster_compute_loop_link_x_positions(GGraphCluster *cluster { GtkAllocation alloc; /* Emplacement à faire évoluer */ gint margin; /* Marge à gauche éventuelle */ - size_t i; /* Boucle de parcours */ + size_t i; /* Boucle de parcours #1 */ + GGraphCluster *start; /* Départ de boucle extérieure */ + GGraphCluster *container; /* Arrivée de boucle extérieure*/ + size_t k; /* Boucle de parcours #2 */ /* Propagation des déterminations */ @@ -2565,11 +2656,32 @@ static void g_graph_cluster_compute_loop_link_x_positions(GGraphCluster *cluster } - /* Liens de boucle */ + /* Liens de boucle (#1) */ g_graph_cluster_compute_needed_alloc(cluster, &alloc); - margin = compute_loop_link_x_with_vspace_manager(&cluster->vspaces, &alloc); + margin = compute_loop_link_x_with_vspace_manager(&cluster->self, &alloc, false); + + /* Liens de boucle (#2) */ + + for (i = 0; i < cluster->ta_count; i++) + if (cluster->top_anchors[i]->type == ILT_LOOP) + { + start = cluster->top_anchors[i]->other->owner; + + container = start->owner; + assert(container != NULL); + + for (k = 0; k < container->ranks_count; k++) + if (has_graph_rank_cluster(&container->ranks[k], start)) + { + margin += compute_loop_link_x_with_vspace_manager(&container->ranks[k].vspaces, &alloc, true); + break; + } + + assert(k < container->ranks_count); + + } g_graph_cluster_insert_left_margin(cluster, margin); @@ -2813,9 +2925,7 @@ static void g_graph_cluster_compute_link_y_positions(GGraphCluster *cluster) /* Définition des liens de boucle */ - g_graph_cluster_compute_needed_alloc(cluster, &alloc); - - compute_loop_link_y_with_vspace_manager(&cluster->vspaces, &alloc); + compute_loop_link_y_with_vspace_manager(&cluster->self, &cluster->alloc); } -- cgit v0.11.2-87-g4458