diff options
-rw-r--r-- | src/gtkext/graph/cluster.c | 704 |
1 files changed, 352 insertions, 352 deletions
diff --git a/src/gtkext/graph/cluster.c b/src/gtkext/graph/cluster.c index 765bbac..16afe57 100644 --- a/src/gtkext/graph/cluster.c +++ b/src/gtkext/graph/cluster.c @@ -97,6 +97,57 @@ static int cmp_incoming_links(const incoming_link_t **, const incoming_link_t ** +/* ------------------------ ENCADREMENTS D'ESPACES VERTICAUX ------------------------ */ + + +/* Réservations d'espaces latéraux */ +typedef struct _vspace_booking_t +{ + leaving_link_t *from; /* Bloc de départ du lien */ + incoming_link_t *to; /* Bloc d'arrivée du lien */ + + GdkPoint *pts; /* Coordonnées des points */ + +} vspace_booking_t; + +/* Réservations d'espaces latéraux */ +typedef struct _vspace_manager_t +{ + vspace_booking_t *pending; /* Besoins exprimés */ + size_t pending_count; /* Nombre de ces besoins */ + + vspace_booking_t **left; /* Lignes disposées à gauche */ + size_t left_count; /* Quantité de ces lignes */ + + vspace_booking_t **right; /* Lignes disposées à droite */ + size_t right_count; /* Quantité de ces lignes */ + +} vspace_manager_t; + + +/* Initialise les réservations liens verticaux. */ +static void init_vspace_manager(vspace_manager_t *); + +/* Termine les réservations liens verticaux. */ +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 *); + +/* Détermine l'emplacement requis pour les espaces latéraux. */ +static void compute_vspace_manager_needed_alloc(const vspace_manager_t *, GtkAllocation *); + +/* Réorganise au besoin les liens de boucle entre blocs. */ +static void sort_incoming_links_for_vspace_manager(vspace_manager_t *); + +/* Détermine les abscisses de tous les liens en place. */ +static void compute_loop_link_x_with_vspace_manager(vspace_manager_t *, GGraphCluster *); + +/* Détermine les ordonnées de tous les liens en place. */ +static void compute_loop_link_y_with_vspace_manager(vspace_manager_t *, GGraphCluster *); + + + /* ---------------------- DESCENDANTS DIRECTS CLASSES PAR RANG ---------------------- */ @@ -175,57 +226,6 @@ static void set_y_for_graph_rank(const graph_rank_t *, gint *); -/* ------------------------ ENCADREMENTS D'ESPACES VERTICAUX ------------------------ */ - - -/* Réservations d'espaces latéraux */ -typedef struct _vspace_booking_t -{ - leaving_link_t *from; /* Bloc de départ du lien */ - incoming_link_t *to; /* Bloc d'arrivée du lien */ - - GdkPoint *pts; /* Coordonnées des points */ - -} vspace_booking_t; - -/* Réservations d'espaces latéraux */ -typedef struct _vspace_manager_t -{ - vspace_booking_t *pending; /* Besoins exprimés */ - size_t pending_count; /* Nombre de ces besoins */ - - vspace_booking_t **left; /* Lignes disposées à gauche */ - size_t left_count; /* Quantité de ces lignes */ - - vspace_booking_t **right; /* Lignes disposées à droite */ - size_t right_count; /* Quantité de ces lignes */ - -} vspace_manager_t; - - -/* Initialise les réservations liens verticaux. */ -static void init_vspace_manager(vspace_manager_t *); - -/* Termine les réservations liens verticaux. */ -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 *); - -/* Détermine l'emplacement requis pour les espaces latéraux. */ -static void compute_vspace_manager_needed_alloc(const vspace_manager_t *, GtkAllocation *); - -/* Réorganise au besoin les liens de boucle entre blocs. */ -static void sort_incoming_links_for_vspace_manager(vspace_manager_t *); - -/* Détermine les abscisses de tous les liens en place. */ -static void compute_loop_link_x_with_vspace_manager(vspace_manager_t *, GGraphCluster *); - -/* Détermine les ordonnées de tous les liens en place. */ -static void compute_loop_link_y_with_vspace_manager(vspace_manager_t *, GGraphCluster *); - - - /* -------------------------- DEFINITION D'UN CHEF DE FILE -------------------------- */ @@ -592,6 +592,307 @@ static int cmp_incoming_links(const incoming_link_t **a, const incoming_link_t * /* ---------------------------------------------------------------------------------- */ +/* ENCADREMENTS D'ESPACES VERTICAUX */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : manager = structure à initialiser. * +* * +* Description : Initialise les réservations liens verticaux. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void init_vspace_manager(vspace_manager_t *manager) +{ + manager->pending = NULL; + manager->pending_count = 0; + + manager->left = NULL; + manager->left_count = 0; + + manager->right = NULL; + manager->right_count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : manager = structure à vider. * +* * +* Description : Termine les réservations liens verticaux. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void exit_vspace_manager(vspace_manager_t *manager) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < manager->pending_count; i++) + free(manager->pending[i].pts); + + if (manager->pending != NULL) + free(manager->pending); + + if (manager->left != NULL) + free(manager->left); + + if (manager->right != NULL) + free(manager->right); + +} + + +/****************************************************************************** +* * +* 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. * +* * +* Description : Inscrit une nouvelle réservation d'espace latéral. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void extend_vspace_manager(vspace_manager_t *manager, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts) +{ + vspace_booking_t *new; /* Réservation à constituer */ + + manager->pending = realloc(manager->pending, ++manager->pending_count * sizeof(vspace_booking_t)); + + new = &manager->pending[manager->pending_count - 1]; + + new->from = from; + new->to = to; + + new->pts = pts; + +} + + +/****************************************************************************** +* * +* Paramètres : manager = gestion des espaces latéraux à consulter. * +* alloc = emplacement idéal pour l'affichage. [OUT] * +* * +* Description : Détermine l'emplacement requis pour les espaces latéraux. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void compute_vspace_manager_needed_alloc(const vspace_manager_t *manager, GtkAllocation *alloc) +{ + gint width; /* Largeur supplémentaire */ + + /* Extension de la largeur */ + + width = 0; + + width += manager->left_count * LINK_MARGIN; + + width += manager->right_count * LINK_MARGIN; + + alloc->x -= width / 2; + alloc->width += width; + + /* Extension de la hauteur */ + + alloc->height += manager->pending_count * VERTICAL_MARGIN; + +} + + +/****************************************************************************** +* * +* Paramètres : manager = gestion d'espaces latéraux à manipuler. * +* * +* Description : Réorganise au besoin les liens de boucle entre blocs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void sort_incoming_links_for_vspace_manager(vspace_manager_t *manager) +{ + size_t i; /* Boucle de parcours */ + vspace_booking_t *pending; /* Elément traité */ + gint x1; /* Abscisse de départ de lien */ + size_t idx; /* Indice du lien entrant */ + gint x2; /* Abscisse d'arrivée de lien */ + + for (i = 0; i < manager->pending_count; i++) + { + pending = &manager->pending[i]; + + x1 = g_graph_cluster_compute_leaving_link_position(pending->from->owner, pending->from->index); + + idx = g_graph_cluster_find_incoming_link(pending->to->owner, pending->from); + + x2 = g_graph_cluster_compute_incoming_link_position(pending->to->owner, idx); + + if (x1 < x2) + { + manager->left = realloc(manager->left, ++manager->left_count * sizeof(vspace_booking_t *)); + manager->left[manager->left_count - 1] = pending; + } + else + { + manager->right = realloc(manager->right, ++manager->right_count * sizeof(vspace_booking_t *)); + manager->right[manager->right_count - 1] = pending; + } + + } + +} + + +/****************************************************************************** +* * +* Paramètres : manager = structure à consulter. * +* cluster = graphique de blocs sur lequel s'appuyer. * +* * +* Description : Détermine les abscisses de tous les liens en place. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void compute_loop_link_x_with_vspace_manager(vspace_manager_t *manager, GGraphCluster *cluster) +{ + GtkAllocation needed; /* Espace nécessaire et alloué */ + size_t i; /* Boucle de parcours */ + vspace_booking_t *booking; /* Réservation à traiter */ + gint x; /* Position à appliquer */ + GGraphCluster *container; /* Parent direct à décaler */ + + g_graph_cluster_compute_needed_alloc(cluster, &needed); + + for (i = 0; i < manager->left_count; i++) + { + booking = manager->left[i]; + + x = i * LINK_MARGIN; + + booking->pts[0].x = needed.x + x; + booking->pts[1].x = needed.x + x; + + } + + if (manager->left_count > 0) + { + x = manager->left_count * LINK_MARGIN; + + /** + * Si la routine est une boucle sans fin, + * alors la boucle peut renvoyer vers le premier bloc. + */ + if (cluster->owner != NULL) + { + container = cluster->owner; + + /** + * On recherche le plus haut propritétaire bénéficiant d'une chaîne + * de liens directs et droits, histoire de transmettre le décalage + * et de garder ces liens bien verticaux. + */ + while (container->owner != NULL) + { + if (!container->owner->has_straight) + break; + + if (container->owner->straight_index != *container->parent_index) + break; + + container = container->owner; + + } + + g_graph_cluster_offset_x(container, x); + + } + + } + + for (i = 0; i < manager->right_count; i++) + { + booking = manager->right[i]; + + x = (i + 1) * LINK_MARGIN; + + booking->pts[0].x = x; + booking->pts[1].x = x; + + } + +} + + +/****************************************************************************** +* * +* Paramètres : manager = structure à consulter. * +* cluster = graphique de blocs sur lequel s'appuyer. * +* * +* Description : Détermine les ordonnées de tous les liens en place. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void compute_loop_link_y_with_vspace_manager(vspace_manager_t *manager, GGraphCluster *cluster) +{ + GtkAllocation needed; /* Espace nécessaire et alloué */ + size_t i; /* Boucle de parcours */ + vspace_booking_t *booking; /* Réservation à traiter */ + + g_graph_cluster_compute_needed_alloc(cluster, &needed); + + for (i = 0; i < manager->pending_count; i++) + { + booking = &manager->pending[i]; + + /** + * On corrige le raccourci pris sans distinction de type de lien dans + * la fonction g_graph_cluster_compute_link_y_positions(). + */ + + booking->from->start[1].y = needed.y + needed.height; + + /* Définition de l'ordonnée des points du lien */ + + booking->pts[0].y = booking->from->start[1].y; + + booking->pts[1].y = booking->to->end[0].y; + + } + +} + + + +/* ---------------------------------------------------------------------------------- */ /* DESCENDANTS DIRECTS CLASSES PAR RANG */ /* ---------------------------------------------------------------------------------- */ @@ -1141,307 +1442,6 @@ static void set_y_for_graph_rank(const graph_rank_t *grank, gint *base) /* ---------------------------------------------------------------------------------- */ -/* ENCADREMENTS D'ESPACES VERTICAUX */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : manager = structure à initialiser. * -* * -* Description : Initialise les réservations liens verticaux. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void init_vspace_manager(vspace_manager_t *manager) -{ - manager->pending = NULL; - manager->pending_count = 0; - - manager->left = NULL; - manager->left_count = 0; - - manager->right = NULL; - manager->right_count = 0; - -} - - -/****************************************************************************** -* * -* Paramètres : manager = structure à vider. * -* * -* Description : Termine les réservations liens verticaux. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void exit_vspace_manager(vspace_manager_t *manager) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < manager->pending_count; i++) - free(manager->pending[i].pts); - - if (manager->pending != NULL) - free(manager->pending); - - if (manager->left != NULL) - free(manager->left); - - if (manager->right != NULL) - free(manager->right); - -} - - -/****************************************************************************** -* * -* 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. * -* * -* Description : Inscrit une nouvelle réservation d'espace latéral. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void extend_vspace_manager(vspace_manager_t *manager, leaving_link_t *from, incoming_link_t *to, GdkPoint *pts) -{ - vspace_booking_t *new; /* Réservation à constituer */ - - manager->pending = realloc(manager->pending, ++manager->pending_count * sizeof(vspace_booking_t)); - - new = &manager->pending[manager->pending_count - 1]; - - new->from = from; - new->to = to; - - new->pts = pts; - -} - - -/****************************************************************************** -* * -* Paramètres : manager = gestion des espaces latéraux à consulter. * -* alloc = emplacement idéal pour l'affichage. [OUT] * -* * -* Description : Détermine l'emplacement requis pour les espaces latéraux. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void compute_vspace_manager_needed_alloc(const vspace_manager_t *manager, GtkAllocation *alloc) -{ - gint width; /* Largeur supplémentaire */ - - /* Extension de la largeur */ - - width = 0; - - width += manager->left_count * LINK_MARGIN; - - width += manager->right_count * LINK_MARGIN; - - alloc->x -= width / 2; - alloc->width += width; - - /* Extension de la hauteur */ - - alloc->height += manager->pending_count * VERTICAL_MARGIN; - -} - - -/****************************************************************************** -* * -* Paramètres : manager = gestion d'espaces latéraux à manipuler. * -* * -* Description : Réorganise au besoin les liens de boucle entre blocs. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void sort_incoming_links_for_vspace_manager(vspace_manager_t *manager) -{ - size_t i; /* Boucle de parcours */ - vspace_booking_t *pending; /* Elément traité */ - gint x1; /* Abscisse de départ de lien */ - size_t idx; /* Indice du lien entrant */ - gint x2; /* Abscisse d'arrivée de lien */ - - for (i = 0; i < manager->pending_count; i++) - { - pending = &manager->pending[i]; - - x1 = g_graph_cluster_compute_leaving_link_position(pending->from->owner, pending->from->index); - - idx = g_graph_cluster_find_incoming_link(pending->to->owner, pending->from); - - x2 = g_graph_cluster_compute_incoming_link_position(pending->to->owner, idx); - - if (x1 < x2) - { - manager->left = realloc(manager->left, ++manager->left_count * sizeof(vspace_booking_t *)); - manager->left[manager->left_count - 1] = pending; - } - else - { - manager->right = realloc(manager->right, ++manager->right_count * sizeof(vspace_booking_t *)); - manager->right[manager->right_count - 1] = pending; - } - - } - -} - - -/****************************************************************************** -* * -* Paramètres : manager = structure à consulter. * -* cluster = graphique de blocs sur lequel s'appuyer. * -* * -* Description : Détermine les abscisses de tous les liens en place. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void compute_loop_link_x_with_vspace_manager(vspace_manager_t *manager, GGraphCluster *cluster) -{ - GtkAllocation needed; /* Espace nécessaire et alloué */ - size_t i; /* Boucle de parcours */ - vspace_booking_t *booking; /* Réservation à traiter */ - gint x; /* Position à appliquer */ - GGraphCluster *container; /* Parent direct à décaler */ - - g_graph_cluster_compute_needed_alloc(cluster, &needed); - - for (i = 0; i < manager->left_count; i++) - { - booking = manager->left[i]; - - x = i * LINK_MARGIN; - - booking->pts[0].x = needed.x + x; - booking->pts[1].x = needed.x + x; - - } - - if (manager->left_count > 0) - { - x = manager->left_count * LINK_MARGIN; - - /** - * Si la routine est une boucle sans fin, - * alors la boucle peut renvoyer vers le premier bloc. - */ - if (cluster->owner != NULL) - { - container = cluster->owner; - - /** - * On recherche le plus haut propritétaire bénéficiant d'une chaîne - * de liens directs et droits, histoire de transmettre le décalage - * et de garder ces liens bien verticaux. - */ - while (container->owner != NULL) - { - if (!container->owner->has_straight) - break; - - if (container->owner->straight_index != *container->parent_index) - break; - - container = container->owner; - - } - - g_graph_cluster_offset_x(container, x); - - } - - } - - for (i = 0; i < manager->right_count; i++) - { - booking = manager->right[i]; - - x = (i + 1) * LINK_MARGIN; - - booking->pts[0].x = x; - booking->pts[1].x = x; - - } - -} - - -/****************************************************************************** -* * -* Paramètres : manager = structure à consulter. * -* cluster = graphique de blocs sur lequel s'appuyer. * -* * -* Description : Détermine les ordonnées de tous les liens en place. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void compute_loop_link_y_with_vspace_manager(vspace_manager_t *manager, GGraphCluster *cluster) -{ - GtkAllocation needed; /* Espace nécessaire et alloué */ - size_t i; /* Boucle de parcours */ - vspace_booking_t *booking; /* Réservation à traiter */ - - g_graph_cluster_compute_needed_alloc(cluster, &needed); - - for (i = 0; i < manager->pending_count; i++) - { - booking = &manager->pending[i]; - - /** - * On corrige le raccourci pris sans distinction de type de lien dans - * la fonction g_graph_cluster_compute_link_y_positions(). - */ - - booking->from->start[1].y = needed.y + needed.height; - - /* Définition de l'ordonnée des points du lien */ - - booking->pts[0].y = booking->from->start[1].y; - - booking->pts[1].y = booking->to->end[0].y; - - } - -} - - - -/* ---------------------------------------------------------------------------------- */ /* DEFINITION D'UN CHEF DE FILE */ /* ---------------------------------------------------------------------------------- */ |