summaryrefslogtreecommitdiff
path: root/src/gtkext/graph/vspace.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtkext/graph/vspace.c')
-rw-r--r--src/gtkext/graph/vspace.c374
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;
+
+ }
+
+}