diff options
Diffstat (limited to 'src/gtkext/graph/vspace.c')
-rw-r--r-- | src/gtkext/graph/vspace.c | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/src/gtkext/graph/vspace.c b/src/gtkext/graph/vspace.c new file mode 100644 index 0000000..8327759 --- /dev/null +++ b/src/gtkext/graph/vspace.c @@ -0,0 +1,374 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * vspace.c - encadrement des espaces verticaux réservés + * + * Copyright (C) 2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "vspace.h" + + +#include <malloc.h> + + +#include "cluster-int.h" + + + +/****************************************************************************** +* * +* Paramètres : manager = structure à initialiser. * +* * +* Description : Initialise les réservations liens verticaux. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +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 : - * +* * +******************************************************************************/ + +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. * +* external = précise une sortie du cadre du cluster premier. * +* * +* Description : Inscrit une nouvelle réservation d'espace latéral. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +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 */ + + 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; + + new->external = external; + +} + + +/****************************************************************************** +* * +* 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. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void compute_vspace_manager_needed_alloc(const vspace_manager_t *manager, bool external, GtkAllocation *alloc) +{ + gint width; /* Largeur supplémentaire */ + size_t count; /* Nombre de liens retenus */ + size_t i; /* Boucle de parcours */ + + width = 0; + + /* 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; + + /* 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 */ + + if (!external) + 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 : - * +* * +******************************************************************************/ + +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 */ + bool for_left; /* Répartition par la gauche ? */ + + 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); + + /** + * Prise en compte d'une boucle while (1); + */ + if (pending->from->owner == pending->to->owner) + for_left = (x2 < x1); + else + for_left = (x1 < x2); + + if (for_left) + { + 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 à actualiser. * +* offset = décalage à appliquer. * +* * +* Description : Décale vers la droite un ensemble de points. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void offset_x_vspace_manager(vspace_manager_t *manager, gint offset) +{ + size_t i; /* Boucle de parcours */ + vspace_booking_t *booking; /* Réservation à traiter */ + + for (i = 0; i < manager->left_count; i++) + { + booking = manager->left[i]; + + booking->pts[0].x += offset; + booking->pts[1].x += offset; + + } + + for (i = 0; i < manager->right_count; i++) + { + booking = manager->right[i]; + + booking->pts[0].x += offset; + booking->pts[1].x += offset; + + } + +} + + +/****************************************************************************** +* * +* 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. * +* * +* Retour : Eventuelle marge à gauche devenue nécessaire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +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]; + + if (booking->external != external) + continue; + + 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]; + + if (booking->external != external) + continue; + + x = ++count * LINK_MARGIN; + + booking->pts[0].x = needed->x + needed->width + x; + booking->pts[1].x = needed->x + needed->width + x; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : manager = structure à consulter. * +* needed = espace nécessaire et alloué pour les blocs. * +* * +* Description : Détermine les ordonnées de tous les liens en place. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void compute_loop_link_y_with_vspace_manager(const vspace_manager_t *manager, const GtkAllocation *needed) +{ + gint real_bottom; /* Point de départ réel */ + size_t i; /* Boucle de parcours */ + vspace_booking_t *booking; /* Réservation à traiter */ + + real_bottom = needed->y + needed->height - manager->pending_count * VERTICAL_MARGIN; + + 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 = real_bottom + (i + 1) * VERTICAL_MARGIN; + + /* 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; + + } + +} |