From 20d9443dbc42b3fe24260f2c4df77cca4d6591b8 Mon Sep 17 00:00:00 2001
From: Camille Ordronneau <camille.ordronneau@inria.fr>
Date: Thu, 30 May 2024 17:08:59 +0200
Subject: [PATCH 1/5] Move part of hpp code to a cpp file

---
 src/CMakeLists.txt      |   1 +
 src/trace/DrawTrace.cpp | 351 +++++++++++++++++++++++++++++++++++++++
 src/trace/DrawTrace.hpp | 357 ++--------------------------------------
 3 files changed, 364 insertions(+), 345 deletions(-)
 create mode 100644 src/trace/DrawTrace.cpp

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 237969bb..601185cf 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -158,6 +158,7 @@ set(VITE_SRCS
   trace/tree/Interval.cpp
   trace/Container.cpp
   trace/ContainerType.cpp
+  trace/DrawTrace.cpp
   trace/Entity.cpp
   trace/EntityType.cpp
   trace/EntityValue.cpp
diff --git a/src/trace/DrawTrace.cpp b/src/trace/DrawTrace.cpp
new file mode 100644
index 00000000..00bb56ab
--- /dev/null
+++ b/src/trace/DrawTrace.cpp
@@ -0,0 +1,351 @@
+/*
+ ** This file is part of the ViTE project.
+ **
+ ** This software is governed by the CeCILL-A license under French law
+ ** and abiding by the rules of distribution of free software. You can
+ ** use, modify and/or redistribute the software under the terms of the
+ ** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
+ ** URL: "http://www.cecill.info".
+ **
+ ** As a counterpart to the access to the source code and rights to copy,
+ ** modify and redistribute granted by the license, users are provided
+ ** only with a limited warranty and the software's author, the holder of
+ ** the economic rights, and the successive licensors have only limited
+ ** liability.
+ **
+ ** In this respect, the user's attention is drawn to the risks associated
+ ** with loading, using, modifying and/or developing or reproducing the
+ ** software by the user in light of its specific status of free software,
+ ** that may mean that it is complicated to manipulate, and that also
+ ** therefore means that it is reserved for developers and experienced
+ ** professionals having in-depth computer knowledge. Users are therefore
+ ** encouraged to load and test the software's suitability as regards
+ ** their requirements in conditions enabling the security of their
+ ** systems and/or data to be ensured and, more generally, to use and
+ ** operate it in the same conditions as regards security.
+ **
+ ** The fact that you are presently reading this means that you have had
+ ** knowledge of the CeCILL-A license and that you accept its terms.
+ **
+ **
+ ** ViTE developers are (for version 0.* to 1.0):
+ **
+ **        - COULOMB Kevin
+ **        - FAVERGE Mathieu
+ **        - JAZEIX Johnny
+ **        - LAGRASSE Olivier
+ **        - MARCOUEILLE Jule
+ **        - NOISETTE Pascal
+ **        - REDONDY Arthur
+ **        - VUCHENER Clément
+ **
+ */
+#include <iostream>
+#include <cassert>
+#include <cmath>
+#include <map>
+#include <vector>
+/* -- */
+#include <QObject>
+/* -- */
+#include "common/common.hpp"
+#include "common/Message.hpp"
+#include "common/Info.hpp"
+/* -- */
+#include "trace/values/Values.hpp"
+/* -- */
+#include "trace/tree/Interval.hpp"
+#include "trace/tree/Node.hpp"
+#include "trace/tree/BinaryTree.hpp"
+/* -- */
+#include "trace/EntityTypes.hpp"
+#include "trace/Entitys.hpp"
+#include "trace/EntityValue.hpp"
+#include "trace/Trace.hpp"
+#include "trace/DrawTree.hpp"
+// #include "trace/values/Value.hpp"
+#include "trace/DrawTrace.hpp"
+
+DrawTrace::DrawTrace() {
+    _container_width = _DRAWING_CONTAINER_WIDTH_DEFAULT;
+    _container_height = _DRAWING_CONTAINER_HEIGHT_DEFAULT;
+    _container_h_space = _DRAWING_CONTAINER_H_SPACE_DEFAULT;
+    _container_v_space = _DRAWING_CONTAINER_V_SPACE_DEFAULT;
+
+    _state_height = _DRAWING_STATE_HEIGHT_DEFAULT;
+    _state_v_space = _DRAWING_STATE_V_SPACE_DEFAULT;
+}
+
+DrawTrace::~DrawTrace() = default;
+
+void DrawTrace::display_information(const Trace *trace, double x, double y, double d) {
+    const Container *container = nullptr;
+    const Container *ancestor = nullptr;
+    const Link *link;
+    const Event *event;
+    const State *state;
+    const Variable *variable;
+
+    // find container needs to know the position of each container
+    Element_pos yr = y;
+    const Container::Vector *root_containers = trace->get_view_root_containers();
+    if (root_containers->empty())
+        root_containers = trace->get_root_containers();
+    if (!root_containers->empty())
+        for (const auto &root_container: *root_containers)
+            if ((container = search_container_by_position(root_container, yr)))
+                break;
+
+    // If the clic is out
+    if (!container)
+        return;
+
+    // Calculate the container positions
+    int position = 0;
+    for (const auto &root_container: *root_containers)
+        position += calc_container_positions(root_container, position);
+
+    // First we browse to find a communication
+    ancestor = container;
+    if (!Info::Render::_no_arrows) {
+
+        while (ancestor) {
+            if ((link = get_link(ancestor, x, y, d))) {
+                *Message::get_instance() << "<center><strong>Link</strong></center>"
+                                         << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />"
+                                         << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />"
+                                         << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />"
+                                         << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />"
+                                         << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />"
+                                         << "<strong>Duration:</strong> " << link->get_duration() << "<br />";
+                print_extra_fields("Link", link->get_extra_fields());
+                print_extra_fields("Value", link->get_value()->get_extra_fields());
+                print_extra_fields("Type", link->get_type()->get_extra_fields());
+                *Message::get_instance() << Message::endsi;
+                return;
+            }
+            else
+                ancestor = ancestor->get_parent();
+        }
+
+        // if not found, the link may hav been assigned to the first root container.
+        if ((link = get_link(root_containers->front(), x, y, d))) {
+            *Message::get_instance() << "<center><strong>Link</strong></center>"
+                                     << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />"
+                                     << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />"
+                                     << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />"
+                                     << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />"
+                                     << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />"
+                                     << "<strong>Duration:</strong> " << link->get_duration() << "<br />";
+            print_extra_fields("Link", link->get_extra_fields());
+            print_extra_fields("Value", link->get_value()->get_extra_fields());
+            print_extra_fields("Type", link->get_type()->get_extra_fields());
+            *Message::get_instance() << Message::endsi;
+            return;
+        }
+    }
+    // Now browsing for the events of the container root
+    // Verification if it is a clic on an event
+#ifndef USE_ITC
+    if ((!container->get_events()->empty() || !container->get_states()->empty()) && yr < _container_height + _container_v_space) {
+#else
+    if (((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) && yr < _container_height + _container_v_space) {
+#endif
+        if (!Info::Render::_no_events)
+            if ((event = find_event(container, x, d))) {
+                *Message::get_instance() << "<center><strong>Event</strong></center>"
+                                         << "<strong>Value:</strong> " << event->get_value()->get_name() << "<br />"
+                                         << "<strong>Container:</strong> " << event->get_container()->get_Name().to_string() << "<br />"
+                                         << "<strong>Type:</strong> " << event->get_type()->get_name() << "<br />"
+                                         << "<strong>Date:</strong> " << event->get_time().get_value() << "<br />";
+                print_extra_fields("Event", event->get_extra_fields());
+                print_extra_fields("Value", event->get_value()->get_extra_fields());
+                print_extra_fields("Type", event->get_type()->get_extra_fields());
+                *Message::get_instance() << Message::endsi;
+                return;
+            }
+        if ((state = find_state(container, x))) {
+            *Message::get_instance() << "<center><strong>State</strong></center>"
+                                     << "<strong>Value:</strong> " << state->get_value()->get_name() << "<br />"
+                                     << "<strong>Container:</strong> " << state->get_container()->get_Name().to_string() << "<br />"
+                                     << "<strong>Type:</strong> " << state->get_type()->get_name() << "<br />"
+                                     << "<strong>Date:</strong> " << state->get_start_time().get_value() << " - " << state->get_end_time().get_value() << "<br />"
+                                     << "<strong>Duration:</strong> " << state->get_duration() << "<br />";
+            print_extra_fields("State", state->get_extra_fields());
+            print_extra_fields("Value", state->get_value()->get_extra_fields());
+            print_extra_fields("Type", state->get_type()->get_extra_fields());
+            *Message::get_instance() << Message::endsi;
+            return;
+        }
+    }
+    else {
+#ifdef USE_ITC
+        if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty()))
+#else
+        if (!container->get_events()->empty() || !container->get_states()->empty())
+#endif
+            yr -= _container_height + _container_v_space;
+        const std::map<VariableType *, Variable *> *variable_map = container->get_variables();
+        std::map<VariableType *, Variable *>::const_iterator i = variable_map->begin();
+        while (yr > _container_height + _container_v_space) {
+            yr -= _container_height + _container_v_space;
+            i++;
+        }
+        if (i != variable_map->end()) {
+            variable = (*i).second;
+            *Message::get_instance() << "<center><strong>Variable</strong></center>"
+                                     << "<strong>Container:</strong> " << variable->get_container()->get_Name().to_string() << "<br />"
+                                     << "<strong>Type:</strong> " << variable->get_type()->get_name() << "<br />"
+                                     << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />"
+                                     << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />"
+                                     << "<strong>Min:</strong> " << variable->get_min().get_value() << "<br />"
+                                     << "<strong>Max:</strong> " << variable->get_max().get_value() << "<br />";
+            print_extra_fields("Type", variable->get_type()->get_extra_fields());
+            *Message::get_instance() << Message::endsi;
+
+            return;
+        }
+    }
+
+    *Message::get_instance() << Message::endsi;
+    // Nothing has been found
+    return;
+}
+
+void DrawTrace::print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields) {
+    if (extra_fields != nullptr && !extra_fields->empty()) {
+        *Message::get_instance() << "<em>" << name << " extra fields</em><br />";
+        for (const auto &extra_field: *extra_fields)
+            *Message::get_instance() << "<strong>" << extra_field.first << ":</strong> " << extra_field.second->to_string() << "<br />";
+    }
+}
+
+const Container *DrawTrace::search_container_by_position(const Container *container, Element_pos &y) {
+    const Container *result;
+    // Search if the result is a descendant
+    const Container::Vector *children = container->get_view_children(); // we want to display only children meant to be displayed
+    if (children->empty())
+        children = container->get_children();
+    for (const auto &i: *children) {
+        if ((result = search_container_by_position(i, y)) != nullptr)
+            return result;
+    }
+
+    // Calculate the size of the container (without its children)
+    int size = 0;
+#ifdef USE_ITC
+    if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty()))
+#else
+    if (!container->get_states()->empty() || !container->get_events()->empty())
+#endif
+        size++;
+    if (container->get_variable_number() > 0)
+        size += container->get_variable_number();
+
+    if (children->empty() && size < 1) // Minimum size
+        size = 1;
+
+    // Test if the position is in this container
+    if (y < size * (_container_height + _container_v_space))
+        return container;
+    else
+        y -= size * (_container_height + _container_v_space);
+
+    // The position is outside this container
+    return nullptr;
+}
+
+int DrawTrace::calc_container_positions(const Container *container, int position) {
+    int size = 0;
+
+    // Draw children
+    const Container::Vector *children = container->get_view_children(); // we want to display only children meant to be displayed
+    if (children->empty())
+        children = container->get_children();
+    for (const auto &i: *children) {
+        size += calc_container_positions(i, position + size);
+    }
+
+    // Store the position to draw links
+    _container_positions[container] = position; // First line after children
+    _container_sizes[container] = size; // First line after children
+
+    // Use one line for states and events
+#ifdef USE_ITC
+    if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) {
+#else
+    if (!container->get_states()->empty() || !container->get_events()->empty()) {
+#endif
+        size++;
+    }
+
+    // Use one line for each variable
+    if (container->get_variable_number() > 0) {
+        size += container->get_variable_number();
+    }
+
+    return size;
+}
+
+const State *DrawTrace::find_state(const Container *container, Element_pos x) {
+    if (!container || container->get_states() == nullptr)
+        return nullptr;
+
+    Node<StateChange> *node = container->get_states()->get_root();
+
+    while (node) {
+        Element_pos t = node->get_element()->get_time().get_value();
+        if (x < t) {
+            if (node->get_element()->get_left_state() && node->get_element()->get_left_state()->get_start_time().get_value() < x)
+                return node->get_element()->get_left_state();
+            node = node->get_left_child();
+        }
+        else {
+            if (node->get_element()->get_right_state() && x < node->get_element()->get_right_state()->get_end_time().get_value())
+                return node->get_element()->get_right_state();
+            node = node->get_right_child();
+        }
+    }
+
+    return nullptr;
+}
+
+bool DrawTrace::link_is_in_set(Link *link, std::vector<const Container *> *set_container, Interval *interval) {
+    const Container *src = link->get_source();
+    const Container *dest = link->get_destination();
+    for (unsigned int i = 0; i < set_container->size(); i++) {
+        if (src == (*set_container)[i]) {
+            for (const auto &j: *set_container)
+                if (dest == j)
+                    if (
+                        (interval->_left.get_value() < link->get_start_time().get_value() && interval->_right.get_value() > link->get_end_time().get_value()) || (interval->_left.get_value() < link->get_end_time().get_value() && interval->_right.get_value() > link->get_start_time().get_value()))
+                        return true;
+        }
+    }
+    return false;
+}
+
+bool DrawTrace::is_in_set(const Container *c, std::vector<const Container *> *set_container) {
+    if (!c || !set_container)
+        return false;
+    for (const auto &i: *set_container)
+        if (c == i)
+            return true;
+    return false;
+}
+
+void DrawTrace::add(std::vector<const Container *> *container, std::stack<Container *> *containers) {
+
+    while (!containers->empty()) {
+        const Container *c = containers->top();
+        containers->pop();
+        const Container::Vector *children = c->get_view_children(); // we want to display only children meant to be displayed
+        if (children->empty())
+            children = c->get_children();
+        for (const auto &i: *children) {
+            containers->push(i);
+            container->push_back(i);
+        }
+        add(container, containers);
+    }
+}
diff --git a/src/trace/DrawTrace.hpp b/src/trace/DrawTrace.hpp
index bf4f481e..e25ab09a 100644
--- a/src/trace/DrawTrace.hpp
+++ b/src/trace/DrawTrace.hpp
@@ -47,10 +47,6 @@
 #ifndef DRAW_TRACE_HPP
 #define DRAW_TRACE_HPP
 
-#include <iostream>
-#include <cassert>
-#include <cmath>
-
 /*
  * Theses constants can not be put as static const float because it is a template and there binary representation is not normed by the C++ langage.
  */
@@ -154,20 +150,12 @@ public:
     /*!
      * \brief The default constructor
      */
-    DrawTrace() {
-        _container_width = _DRAWING_CONTAINER_WIDTH_DEFAULT;
-        _container_height = _DRAWING_CONTAINER_HEIGHT_DEFAULT;
-        _container_h_space = _DRAWING_CONTAINER_H_SPACE_DEFAULT;
-        _container_v_space = _DRAWING_CONTAINER_V_SPACE_DEFAULT;
-
-        _state_height = _DRAWING_STATE_HEIGHT_DEFAULT;
-        _state_v_space = _DRAWING_STATE_V_SPACE_DEFAULT;
-    }
+    DrawTrace();
 
     /*!
      * \brief The destructor
      */
-    virtual ~DrawTrace() = default;
+    virtual ~DrawTrace();
 
     /***********************************
      *
@@ -585,354 +573,33 @@ public:
     /*
      * \brief Assuming someone has clicked in (x, y), display the description corresponding to the item clicked
      */
-    void display_information(const Trace *trace, double x, double y, double d) {
-        const Container *container = nullptr;
-        const Container *ancestor = nullptr;
-        const Link *link;
-        const Event *event;
-        const State *state;
-        const Variable *variable;
-
-        // find container needs to know the position of each container
-        Element_pos yr = y;
-        const Container::Vector *root_containers = trace->get_view_root_containers();
-        if (root_containers->empty())
-            root_containers = trace->get_root_containers();
-        if (!root_containers->empty())
-            for (const auto &root_container: *root_containers)
-                if ((container = search_container_by_position(root_container, yr)))
-                    break;
-
-        // If the clic is out
-        if (!container)
-            return;
-
-        // Calculate the container positions
-        int position = 0;
-        for (const auto &root_container: *root_containers)
-            position += calc_container_positions(root_container, position);
-
-        // First we browse to find a communication
-        ancestor = container;
-        if (!Info::Render::_no_arrows) {
-
-            while (ancestor) {
-                if ((link = get_link(ancestor, x, y, d))) {
-                    *Message::get_instance() << "<center><strong>Link</strong></center>"
-                                             << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />"
-                                             << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />"
-                                             << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />"
-                                             << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />"
-                                             << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />"
-                                             << "<strong>Duration:</strong> " << link->get_duration() << "<br />";
-                    print_extra_fields("Link", link->get_extra_fields());
-                    print_extra_fields("Value", link->get_value()->get_extra_fields());
-                    print_extra_fields("Type", link->get_type()->get_extra_fields());
-                    *Message::get_instance() << Message::endsi;
-                    return;
-                }
-                else
-                    ancestor = ancestor->get_parent();
-            }
-
-            // if not found, the link may hav been assigned to the first root container.
-            if ((link = get_link(root_containers->front(), x, y, d))) {
-                *Message::get_instance() << "<center><strong>Link</strong></center>"
-                                         << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />"
-                                         << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />"
-                                         << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />"
-                                         << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />"
-                                         << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />"
-                                         << "<strong>Duration:</strong> " << link->get_duration() << "<br />";
-                print_extra_fields("Link", link->get_extra_fields());
-                print_extra_fields("Value", link->get_value()->get_extra_fields());
-                print_extra_fields("Type", link->get_type()->get_extra_fields());
-                *Message::get_instance() << Message::endsi;
-                return;
-            }
-        }
-        // Now browsing for the events of the container root
-        // Verification if it is a clic on an event
-#ifndef USE_ITC
-        if ((!container->get_events()->empty() || !container->get_states()->empty()) && yr < _container_height + _container_v_space) {
-#else
-        if (((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) && yr < _container_height + _container_v_space) {
-#endif
-            if (!Info::Render::_no_events)
-                if ((event = find_event(container, x, d))) {
-                    *Message::get_instance() << "<center><strong>Event</strong></center>"
-                                             << "<strong>Value:</strong> " << event->get_value()->get_name() << "<br />"
-                                             << "<strong>Container:</strong> " << event->get_container()->get_Name().to_string() << "<br />"
-                                             << "<strong>Type:</strong> " << event->get_type()->get_name() << "<br />"
-                                             << "<strong>Date:</strong> " << event->get_time().get_value() << "<br />";
-                    print_extra_fields("Event", event->get_extra_fields());
-                    print_extra_fields("Value", event->get_value()->get_extra_fields());
-                    print_extra_fields("Type", event->get_type()->get_extra_fields());
-                    *Message::get_instance() << Message::endsi;
-                    return;
-                }
-            if ((state = find_state(container, x))) {
-                *Message::get_instance() << "<center><strong>State</strong></center>"
-                                         << "<strong>Value:</strong> " << state->get_value()->get_name() << "<br />"
-                                         << "<strong>Container:</strong> " << state->get_container()->get_Name().to_string() << "<br />"
-                                         << "<strong>Type:</strong> " << state->get_type()->get_name() << "<br />"
-                                         << "<strong>Date:</strong> " << state->get_start_time().get_value() << " - " << state->get_end_time().get_value() << "<br />"
-                                         << "<strong>Duration:</strong> " << state->get_duration() << "<br />";
-                print_extra_fields("State", state->get_extra_fields());
-                print_extra_fields("Value", state->get_value()->get_extra_fields());
-                print_extra_fields("Type", state->get_type()->get_extra_fields());
-                *Message::get_instance() << Message::endsi;
-                return;
-            }
-        }
-        else {
-#ifdef USE_ITC
-            if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty()))
-#else
-            if (!container->get_events()->empty() || !container->get_states()->empty())
-#endif
-                yr -= _container_height + _container_v_space;
-            const std::map<VariableType *, Variable *> *variable_map = container->get_variables();
-            std::map<VariableType *, Variable *>::const_iterator i = variable_map->begin();
-            while (yr > _container_height + _container_v_space) {
-                yr -= _container_height + _container_v_space;
-                i++;
-            }
-            if (i != variable_map->end()) {
-                variable = (*i).second;
-                *Message::get_instance() << "<center><strong>Variable</strong></center>"
-                                         << "<strong>Container:</strong> " << variable->get_container()->get_Name().to_string() << "<br />"
-                                         << "<strong>Type:</strong> " << variable->get_type()->get_name() << "<br />"
-                                         << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />"
-                                         << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />"
-                                         << "<strong>Min:</strong> " << variable->get_min().get_value() << "<br />"
-                                         << "<strong>Max:</strong> " << variable->get_max().get_value() << "<br />";
-                print_extra_fields("Type", variable->get_type()->get_extra_fields());
-                *Message::get_instance() << Message::endsi;
-
-                return;
-            }
-        }
-
-        *Message::get_instance() << Message::endsi;
-        // Nothing has been found
-        return;
-    }
-
-    void print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields) {
-        if (extra_fields != nullptr && !extra_fields->empty()) {
-            *Message::get_instance() << "<em>" << name << " extra fields</em><br />";
-            for (const auto &extra_field: *extra_fields)
-                *Message::get_instance() << "<strong>" << extra_field.first << ":</strong> " << extra_field.second->to_string() << "<br />";
-        }
-    }
-
-    const Container *search_container_by_position(const Container *container, Element_pos &y) {
-        const Container *result;
-        // Search if the result is a descendant
-        const Container::Vector *children = container->get_view_children(); // we want to display only children meant to be displayed
-        if (children->empty())
-            children = container->get_children();
-        for (const auto &i: *children) {
-            if ((result = search_container_by_position(i, y)) != nullptr)
-                return result;
-        }
-
-        // Calculate the size of the container (without its children)
-        int size = 0;
-#ifdef USE_ITC
-        if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty()))
-#else
-        if (!container->get_states()->empty() || !container->get_events()->empty())
-#endif
-            size++;
-        if (container->get_variable_number() > 0)
-            size += container->get_variable_number();
+    void display_information(const Trace *trace, double x, double y, double d);
 
-        if (children->empty() && size < 1) // Minimum size
-            size = 1;
+    void print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields);
 
-        // Test if the position is in this container
-        if (y < size * (_container_height + _container_v_space))
-            return container;
-        else
-            y -= size * (_container_height + _container_v_space);
-
-        // The position is outside this container
-        return nullptr;
-    }
+    const Container *search_container_by_position(const Container *container, Element_pos &y);
 
     /*
      * \fn browse_container(T* draw_object, const Container *container, int position, int depth)
      * \brief Recursive function that browse a container to draw it with a T painting object in position, knowing the current depth in the tree
      */
-    int calc_container_positions(const Container *container, int position) {
-        int size = 0;
-
-        // Draw children
-        const Container::Vector *children = container->get_view_children(); // we want to display only children meant to be displayed
-        if (children->empty())
-            children = container->get_children();
-        for (const auto &i: *children) {
-            size += calc_container_positions(i, position + size);
-        }
-
-        // Store the position to draw links
-        _container_positions[container] = position; // First line after children
-        _container_sizes[container] = size; // First line after children
-
-        // Use one line for states and events
-#ifdef USE_ITC
-        if ((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) {
-#else
-        if (!container->get_states()->empty() || !container->get_events()->empty()) {
-#endif
-            size++;
-        }
-
-        // Use one line for each variable
-        if (container->get_variable_number() > 0) {
-            size += container->get_variable_number();
-        }
-
-        return size;
-    }
+    int calc_container_positions(const Container *container, int position);
 
     /*!
-     * \brief Tries to find a link passing by x and y in the container
-     */
-    const Link *get_link(const Container *container, Element_pos x, Element_pos y, Element_pos d) {
-        const Link::Vector *link_list;
-        Link *link;
-        double a, b, c; // Equation: ax + by + c = 0
-        double x1, x2, y1, y2;
-
-        if (!container)
-            return nullptr;
-
-        // Browse links
-        link_list = container->get_links();
-        for (const auto &it: *link_list) {
-
-            link = it;
-
-            double srcpos = _container_positions[link->get_source()];
-            double dstpos = _container_positions[link->get_destination()];
-            double srcsize = _container_sizes[link->get_source()];
-            double dstsize = _container_sizes[link->get_destination()];
-
-            x1 = link->get_start_time().get_value();
-            x2 = link->get_end_time().get_value();
-
-            y1 = (srcpos + 0.5 * srcsize) * (_container_height + _container_v_space);
-            y2 = (dstpos + 0.5 * dstsize) * (_container_height + _container_v_space);
-
-            if (((x1 - d <= x && x <= x2 + d) || (x2 - d <= x && x <= x1 + d)) && ((y1 - d <= y && y <= y2 + d) || (y2 - d <= y && y <= y1 + d))) { // Test the interval
-                a = y1 - y2;
-                b = x2 - x1;
-                c = -(a * x1 + b * y1);
-
-                double e = a * x + b * y + c;
-
-                if (e * e / (a * a + b * b) < d * d) // Test the distance
-                    return link;
-            }
-        }
-
-        return nullptr;
-    }
-
-    /*
-     * \brief Returns the event that occurs at the time x in the container
+     * \brief Tries to find all links passing by x and y in the container
      */
-    const Event *find_event(const Container *container, Element_pos x, Element_pos d) {
-        if (!container || container->get_events() == nullptr)
-            return nullptr;
-
-        Node<Event> *node = container->get_events()->get_root();
-
-        while (node) {
-            Element_pos t = node->get_element()->get_time().get_value();
-            if (x < t) {
-                if (t - x < d)
-                    return node->get_element();
-                node = node->get_left_child();
-            }
-            else {
-                if (x - t < d)
-                    return node->get_element();
-                node = node->get_right_child();
-            }
-        }
-
-        return nullptr;
-    }
+    const Event *find_event(const Container *container, Element_pos x, Element_pos d);
 
     /*
      * \brief Returns the state at the time x
      */
-    const State *find_state(const Container *container, Element_pos x) {
-        if (!container || container->get_states() == nullptr)
-            return nullptr;
-
-        Node<StateChange> *node = container->get_states()->get_root();
-
-        while (node) {
-            Element_pos t = node->get_element()->get_time().get_value();
-            if (x < t) {
-                if (node->get_element()->get_left_state() && node->get_element()->get_left_state()->get_start_time().get_value() < x)
-                    return node->get_element()->get_left_state();
-                node = node->get_left_child();
-            }
-            else {
-                if (node->get_element()->get_right_state() && x < node->get_element()->get_right_state()->get_end_time().get_value())
-                    return node->get_element()->get_right_state();
-                node = node->get_right_child();
-            }
-        }
+    const State *find_state(const Container *container, Element_pos x);
 
-        return nullptr;
-    }
-
-    bool link_is_in_set(Link *link, std::vector<const Container *> *set_container, Interval *interval) {
-        const Container *src = link->get_source();
-        const Container *dest = link->get_destination();
-        for (unsigned int i = 0; i < set_container->size(); i++) {
-            if (src == (*set_container)[i]) {
-                for (const auto &j: *set_container)
-                    if (dest == j)
-                        if (
-                            (interval->_left.get_value() < link->get_start_time().get_value() && interval->_right.get_value() > link->get_end_time().get_value()) || (interval->_left.get_value() < link->get_end_time().get_value() && interval->_right.get_value() > link->get_start_time().get_value()))
-                            return true;
-            }
-        }
-        return false;
-    }
+    bool link_is_in_set(Link *link, std::vector<const Container *> *set_container, Interval *interval);
 
-    bool is_in_set(const Container *c, std::vector<const Container *> *set_container) {
-        if (!c || !set_container)
-            return false;
-        for (const auto &i: *set_container)
-            if (c == i)
-                return true;
-        return false;
-    }
+    bool is_in_set(const Container *c, std::vector<const Container *> *set_container);
 
-    void add(std::vector<const Container *> *container, std::stack<Container *> *containers) {
-
-        while (!containers->empty()) {
-            const Container *c = containers->top();
-            containers->pop();
-            const Container::Vector *children = c->get_view_children(); // we want to display only children meant to be displayed
-            if (children->empty())
-                children = c->get_children();
-            for (const auto &i: *children) {
-                containers->push(i);
-                container->push_back(i);
-            }
-            add(container, containers);
-        }
-    }
+    void add(std::vector<const Container *> *container, std::stack<Container *> *containers);
 
     template <class T>
     void draw_text_variable_values(T *render, std::map<long int, double> *var_map, double date) {
-- 
GitLab


From 067e3a49f2da702b9b0ab22c9f13cd4046d96de8 Mon Sep 17 00:00:00 2001
From: Ordronneau Camille <camille.ordronneau@inria.fr>
Date: Thu, 23 May 2024 16:43:20 +0200
Subject: [PATCH 2/5] Add functions for clearer code

---
 src/trace/DrawTrace.cpp | 123 +++++++++++++++++++++-------------------
 src/trace/DrawTrace.hpp |   2 -
 2 files changed, 64 insertions(+), 61 deletions(-)

diff --git a/src/trace/DrawTrace.cpp b/src/trace/DrawTrace.cpp
index 00bb56ab..02951e3f 100644
--- a/src/trace/DrawTrace.cpp
+++ b/src/trace/DrawTrace.cpp
@@ -78,6 +78,65 @@ DrawTrace::DrawTrace() {
 
 DrawTrace::~DrawTrace() = default;
 
+void print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields) {
+    if (extra_fields != nullptr && !extra_fields->empty()) {
+        *Message::get_instance() << "<em>" << name << " extra fields</em><br />";
+        for (const auto &extra_field: *extra_fields)
+            *Message::get_instance() << "<strong>" << extra_field.first << ":</strong> " << extra_field.second->to_string() << "<br />";
+    }
+}
+
+void display_link_info(const Link *link) {
+    *Message::get_instance() << "<center><strong>Link</strong></center>"
+                             << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />"
+                             << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />"
+                             << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />"
+                             << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />"
+                             << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />"
+                             << "<strong>Duration:</strong> " << link->get_duration() << "<br />";
+    print_extra_fields("Link", link->get_extra_fields());
+    print_extra_fields("Value", link->get_value()->get_extra_fields());
+    print_extra_fields("Type", link->get_type()->get_extra_fields());
+    *Message::get_instance() << Message::endsi;
+}
+
+void display_event_info(const Event *event) {
+    *Message::get_instance() << "<center><strong>Event</strong></center>"
+                             << "<strong>Value:</strong> " << event->get_value()->get_name() << "<br />"
+                             << "<strong>Container:</strong> " << event->get_container()->get_Name().to_string() << "<br />"
+                             << "<strong>Type:</strong> " << event->get_type()->get_name() << "<br />"
+                             << "<strong>Date:</strong> " << event->get_time().get_value() << "<br />";
+    print_extra_fields("Event", event->get_extra_fields());
+    print_extra_fields("Value", event->get_value()->get_extra_fields());
+    print_extra_fields("Type", event->get_type()->get_extra_fields());
+    *Message::get_instance() << Message::endsi;
+}
+
+void display_state_info(const State *state) {
+    *Message::get_instance() << "<center><strong>State</strong></center>"
+                             << "<strong>Value:</strong> " << state->get_value()->get_name() << "<br />"
+                             << "<strong>Container:</strong> " << state->get_container()->get_Name().to_string() << "<br />"
+                             << "<strong>Type:</strong> " << state->get_type()->get_name() << "<br />"
+                             << "<strong>Date:</strong> " << state->get_start_time().get_value() << " - " << state->get_end_time().get_value() << "<br />"
+                             << "<strong>Duration:</strong> " << state->get_duration() << "<br />";
+    print_extra_fields("State", state->get_extra_fields());
+    print_extra_fields("Value", state->get_value()->get_extra_fields());
+    print_extra_fields("Type", state->get_type()->get_extra_fields());
+    *Message::get_instance() << Message::endsi;
+}
+
+void display_variable_info(const Variable *variable, const double &x) {
+    *Message::get_instance() << "<center><strong>Variable</strong></center>"
+                             << "<strong>Container:</strong> " << variable->get_container()->get_Name().to_string() << "<br />"
+                             << "<strong>Type:</strong> " << variable->get_type()->get_name() << "<br />"
+                             << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />"
+                             << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />"
+                             << "<strong>Min:</strong> " << variable->get_min().get_value() << "<br />"
+                             << "<strong>Max:</strong> " << variable->get_max().get_value() << "<br />";
+    print_extra_fields("Type", variable->get_type()->get_extra_fields());
+    *Message::get_instance() << Message::endsi;
+}
+
 void DrawTrace::display_information(const Trace *trace, double x, double y, double d) {
     const Container *container = nullptr;
     const Container *ancestor = nullptr;
@@ -111,17 +170,7 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub
 
         while (ancestor) {
             if ((link = get_link(ancestor, x, y, d))) {
-                *Message::get_instance() << "<center><strong>Link</strong></center>"
-                                         << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />"
-                                         << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />"
-                                         << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />"
-                                         << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />"
-                                         << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />"
-                                         << "<strong>Duration:</strong> " << link->get_duration() << "<br />";
-                print_extra_fields("Link", link->get_extra_fields());
-                print_extra_fields("Value", link->get_value()->get_extra_fields());
-                print_extra_fields("Type", link->get_type()->get_extra_fields());
-                *Message::get_instance() << Message::endsi;
+                display_link_info(link);
                 return;
             }
             else
@@ -130,17 +179,7 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub
 
         // if not found, the link may hav been assigned to the first root container.
         if ((link = get_link(root_containers->front(), x, y, d))) {
-            *Message::get_instance() << "<center><strong>Link</strong></center>"
-                                     << "<strong>Value:</strong> " << link->get_value()->get_name() << "<br />"
-                                     << "<strong>Source:</strong> " << link->get_source()->get_Name().to_string() << "<br />"
-                                     << "<strong>Destination:</strong> " << link->get_destination()->get_Name().to_string() << "<br />"
-                                     << "<strong>Type:</strong> " << link->get_type()->get_name() << "<br />"
-                                     << "<strong>Date:</strong> " << link->get_start_time().get_value() << " - " << link->get_end_time().get_value() << "<br />"
-                                     << "<strong>Duration:</strong> " << link->get_duration() << "<br />";
-            print_extra_fields("Link", link->get_extra_fields());
-            print_extra_fields("Value", link->get_value()->get_extra_fields());
-            print_extra_fields("Type", link->get_type()->get_extra_fields());
-            *Message::get_instance() << Message::endsi;
+            display_link_info(link);
             return;
         }
     }
@@ -153,28 +192,11 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub
 #endif
         if (!Info::Render::_no_events)
             if ((event = find_event(container, x, d))) {
-                *Message::get_instance() << "<center><strong>Event</strong></center>"
-                                         << "<strong>Value:</strong> " << event->get_value()->get_name() << "<br />"
-                                         << "<strong>Container:</strong> " << event->get_container()->get_Name().to_string() << "<br />"
-                                         << "<strong>Type:</strong> " << event->get_type()->get_name() << "<br />"
-                                         << "<strong>Date:</strong> " << event->get_time().get_value() << "<br />";
-                print_extra_fields("Event", event->get_extra_fields());
-                print_extra_fields("Value", event->get_value()->get_extra_fields());
-                print_extra_fields("Type", event->get_type()->get_extra_fields());
-                *Message::get_instance() << Message::endsi;
+                display_event_info(event);
                 return;
             }
         if ((state = find_state(container, x))) {
-            *Message::get_instance() << "<center><strong>State</strong></center>"
-                                     << "<strong>Value:</strong> " << state->get_value()->get_name() << "<br />"
-                                     << "<strong>Container:</strong> " << state->get_container()->get_Name().to_string() << "<br />"
-                                     << "<strong>Type:</strong> " << state->get_type()->get_name() << "<br />"
-                                     << "<strong>Date:</strong> " << state->get_start_time().get_value() << " - " << state->get_end_time().get_value() << "<br />"
-                                     << "<strong>Duration:</strong> " << state->get_duration() << "<br />";
-            print_extra_fields("State", state->get_extra_fields());
-            print_extra_fields("Value", state->get_value()->get_extra_fields());
-            print_extra_fields("Type", state->get_type()->get_extra_fields());
-            *Message::get_instance() << Message::endsi;
+            display_state_info(state);
             return;
         }
     }
@@ -193,16 +215,7 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub
         }
         if (i != variable_map->end()) {
             variable = (*i).second;
-            *Message::get_instance() << "<center><strong>Variable</strong></center>"
-                                     << "<strong>Container:</strong> " << variable->get_container()->get_Name().to_string() << "<br />"
-                                     << "<strong>Type:</strong> " << variable->get_type()->get_name() << "<br />"
-                                     << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />"
-                                     << "<strong>Value:</strong> " << variable->get_value_at(x) << "<br />"
-                                     << "<strong>Min:</strong> " << variable->get_min().get_value() << "<br />"
-                                     << "<strong>Max:</strong> " << variable->get_max().get_value() << "<br />";
-            print_extra_fields("Type", variable->get_type()->get_extra_fields());
-            *Message::get_instance() << Message::endsi;
-
+            display_variable_info(variable, x);
             return;
         }
     }
@@ -212,14 +225,6 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub
     return;
 }
 
-void DrawTrace::print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields) {
-    if (extra_fields != nullptr && !extra_fields->empty()) {
-        *Message::get_instance() << "<em>" << name << " extra fields</em><br />";
-        for (const auto &extra_field: *extra_fields)
-            *Message::get_instance() << "<strong>" << extra_field.first << ":</strong> " << extra_field.second->to_string() << "<br />";
-    }
-}
-
 const Container *DrawTrace::search_container_by_position(const Container *container, Element_pos &y) {
     const Container *result;
     // Search if the result is a descendant
diff --git a/src/trace/DrawTrace.hpp b/src/trace/DrawTrace.hpp
index e25ab09a..580bd1a9 100644
--- a/src/trace/DrawTrace.hpp
+++ b/src/trace/DrawTrace.hpp
@@ -575,8 +575,6 @@ public:
      */
     void display_information(const Trace *trace, double x, double y, double d);
 
-    void print_extra_fields(const std::string &name, const std::map<std::string, Value *> *extra_fields);
-
     const Container *search_container_by_position(const Container *container, Element_pos &y);
 
     /*
-- 
GitLab


From 126f068d8a5c8aec4f09366e37081aa72731caff Mon Sep 17 00:00:00 2001
From: Ordronneau Camille <camille.ordronneau@inria.fr>
Date: Tue, 28 May 2024 10:32:50 +0200
Subject: [PATCH 3/5] Add getting all Entities when double clicking

---
 src/trace/DrawTrace.cpp | 116 ++++++++++++++++++++++++++++++++--------
 src/trace/DrawTrace.hpp |   2 +-
 2 files changed, 96 insertions(+), 22 deletions(-)

diff --git a/src/trace/DrawTrace.cpp b/src/trace/DrawTrace.cpp
index 02951e3f..73ccf9c9 100644
--- a/src/trace/DrawTrace.cpp
+++ b/src/trace/DrawTrace.cpp
@@ -52,6 +52,8 @@
 #include "common/Message.hpp"
 #include "common/Info.hpp"
 /* -- */
+#include "interface/Interface.hpp"
+/* -- */
 #include "trace/values/Values.hpp"
 /* -- */
 #include "trace/tree/Interval.hpp"
@@ -137,11 +139,80 @@ void display_variable_info(const Variable *variable, const double &x) {
     *Message::get_instance() << Message::endsi;
 }
 
+void DrawTrace::fill_link_list(const Container *container, const Element_pos &x, const Element_pos &y, const Element_pos &accuracy, Link::Vector *link_list) {
+    const Link::Vector *container_links;
+    Link *link;
+    double a, b, c; // Equation: ax + by + c = 0
+    double x1, x2, y1, y2;
+
+    if (!container)
+        return;
+
+    // Browse links
+    container_links = container->get_links();
+    for (const auto &it: *container_links) {
+        link = it;
+
+        double srcpos = _container_positions[link->get_source()];
+        double dstpos = _container_positions[link->get_destination()];
+        double srcsize = _container_sizes[link->get_source()];
+        double dstsize = _container_sizes[link->get_destination()];
+
+        x1 = link->get_start_time().get_value();
+        x2 = link->get_end_time().get_value();
+
+        y1 = (srcpos + 0.5 * srcsize) * (_container_height + _container_v_space);
+        y2 = (dstpos + 0.5 * dstsize) * (_container_height + _container_v_space);
+
+        // Test if (x, y) is in the counding box made by the link ends
+        if (((x1 - accuracy <= x && x <= x2 + accuracy) || (x2 - accuracy <= x && x <= x1 + accuracy)) && ((y1 - accuracy <= y && y <= y2 + accuracy) || (y2 - accuracy <= y && y <= y1 + accuracy))) {
+            a = y1 - y2;
+            b = x2 - x1;
+            c = -(a * x1 + b * y1);
+
+            double e = a * x + b * y + c;
+
+            // Test the distance from (x, y) to the link
+            if (e * e / (a * a + b * b) < accuracy) {
+                link_list->push_back(link);
+            }
+        }
+    }
+
+    return;
+}
+
+void fill_event_list(const Node<Event> *node, const Element_pos &x, const Element_pos &d, std::list<const Event *> *event_list) {
+
+    if (nullptr == node) {
+        return;
+    }
+
+    const Element_pos t = node->get_element()->get_time().get_value();
+
+    if (t < x) {
+        if (x - t < d) {
+            fill_event_list(node->get_left_child(), x, d, event_list);
+            event_list->push_back(node->get_element());
+        }
+        fill_event_list(node->get_right_child(), x, d, event_list);
+        return;
+    }
+
+    fill_event_list(node->get_left_child(), x, d, event_list);
+    if (t - x < d) {
+        event_list->push_back(node->get_element());
+        fill_event_list(node->get_right_child(), x, d, event_list);
+    }
+    return;
+}
+
 void DrawTrace::display_information(const Trace *trace, double x, double y, double d) {
     const Container *container = nullptr;
     const Container *ancestor = nullptr;
-    const Link *link;
-    const Event *event;
+
+    Link::Vector link_list;
+    std::list<const Event *> event_list;
     const State *state;
     const Variable *variable;
 
@@ -166,21 +237,19 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub
 
     // First we browse to find a communication
     ancestor = container;
-    if (!Info::Render::_no_arrows) {
 
+    Message::get_interface()->selection_information_clear();
+    if (!Info::Render::_no_arrows) {
         while (ancestor) {
-            if ((link = get_link(ancestor, x, y, d))) {
-                display_link_info(link);
-                return;
-            }
-            else
-                ancestor = ancestor->get_parent();
+            fill_link_list(ancestor, x, y, d, &link_list);
+            ancestor = ancestor->get_parent();
         }
-
-        // if not found, the link may hav been assigned to the first root container.
-        if ((link = get_link(root_containers->front(), x, y, d))) {
+        fill_link_list(root_containers->front(), x, y, d, &link_list);
+        int i = 1;
+        for (auto const &link: link_list) {
+            Message::get_interface()->selection_information_new_tab("Link " + std::to_string(i));
             display_link_info(link);
-            return;
+            i++;
         }
     }
     // Now browsing for the events of the container root
@@ -190,14 +259,20 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub
 #else
     if (((container->get_states() != NULL && !container->get_states()->empty()) || (container->get_events() != NULL && !container->get_events()->empty())) && yr < _container_height + _container_v_space) {
 #endif
-        if (!Info::Render::_no_events)
-            if ((event = find_event(container, x, d))) {
-                display_event_info(event);
-                return;
+        if (!Info::Render::_no_events) {
+            if (container->get_events() != nullptr) {
+                fill_event_list(container->get_events()->get_root(), x, d, &event_list);
+                int i = 1;
+                for (auto const &event: event_list) {
+                    Message::get_interface()->selection_information_new_tab("Event " + std::to_string(i));
+                    display_event_info(event);
+                    i++;
+                }
             }
+        }
         if ((state = find_state(container, x))) {
+            Message::get_interface()->selection_information_new_tab("State");
             display_state_info(state);
-            return;
         }
     }
     else {
@@ -215,12 +290,11 @@ void DrawTrace::display_information(const Trace *trace, double x, double y, doub
         }
         if (i != variable_map->end()) {
             variable = (*i).second;
+            Message::get_interface()->selection_information_new_tab("Variable");
             display_variable_info(variable, x);
-            return;
         }
     }
-
-    *Message::get_instance() << Message::endsi;
+    Message::get_interface()->selection_information_show();
     // Nothing has been found
     return;
 }
diff --git a/src/trace/DrawTrace.hpp b/src/trace/DrawTrace.hpp
index 580bd1a9..44a1f0ee 100644
--- a/src/trace/DrawTrace.hpp
+++ b/src/trace/DrawTrace.hpp
@@ -586,7 +586,7 @@ public:
     /*!
      * \brief Tries to find all links passing by x and y in the container
      */
-    const Event *find_event(const Container *container, Element_pos x, Element_pos d);
+    void fill_link_list(const Container *container, const Element_pos &x, const Element_pos &y, const Element_pos &d, Link::Vector *link_list);
 
     /*
      * \brief Returns the state at the time x
-- 
GitLab


From acc0d109880aa82183a2c5ba4b591c1b52bd92d8 Mon Sep 17 00:00:00 2001
From: Ordronneau Camille <camille.ordronneau@inria.fr>
Date: Fri, 24 May 2024 16:49:43 +0200
Subject: [PATCH 4/5] Change information window ui, textEdit became QTabWidget

---
 src/interface/info_window.ui | 114 ++++++++++++++---------------------
 1 file changed, 46 insertions(+), 68 deletions(-)

diff --git a/src/interface/info_window.ui b/src/interface/info_window.ui
index 032e20b9..ae159c4c 100644
--- a/src/interface/info_window.ui
+++ b/src/interface/info_window.ui
@@ -1,7 +1,8 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
  <class>info_window</class>
- <widget class="QMainWindow" name="info_window" >
-  <property name="geometry" >
+ <widget class="QMainWindow" name="info_window">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
@@ -9,53 +10,56 @@
     <height>229</height>
    </rect>
   </property>
-  <property name="windowTitle" >
+  <property name="windowTitle">
    <string>Informations</string>
   </property>
-  <property name="windowIcon" >
-   <iconset resource="vite.qrc" >
+  <property name="windowIcon">
+   <iconset resource="vite.qrc">
     <normaloff>:/icon/icon/vite.png</normaloff>:/icon/icon/vite.png</iconset>
   </property>
-  <widget class="QWidget" name="centralwidget" >
-   <layout class="QHBoxLayout" name="horizontalLayout_2" >
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QHBoxLayout" name="horizontalLayout_2">
     <item>
-     <layout class="QHBoxLayout" name="horizontalLayout" >
-      <property name="rightMargin" >
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <property name="rightMargin">
        <number>0</number>
       </property>
-      <property name="bottomMargin" >
+      <property name="bottomMargin">
        <number>0</number>
       </property>
       <item>
-       <layout class="QVBoxLayout" name="verticalLayout_3" >
-        <property name="rightMargin" >
+       <layout class="QVBoxLayout" name="verticalLayout_3">
+        <property name="rightMargin">
          <number>0</number>
         </property>
         <item>
-         <widget class="QGroupBox" name="info_trace" >
-          <property name="focusPolicy" >
+         <widget class="QGroupBox" name="info_trace">
+          <property name="focusPolicy">
            <enum>Qt::StrongFocus</enum>
           </property>
-          <property name="title" >
+          <property name="title">
            <string>Trace Resume</string>
           </property>
-          <layout class="QHBoxLayout" name="horizontalLayout_3" >
+          <layout class="QHBoxLayout" name="horizontalLayout_3">
            <item>
-            <widget class="QTextEdit" name="info_trace_text" >
-             <property name="verticalScrollBarPolicy" >
+            <widget class="QTextEdit" name="info_trace_text">
+             <property name="verticalScrollBarPolicy">
               <enum>Qt::ScrollBarAsNeeded</enum>
              </property>
-             <property name="readOnly" >
+             <property name="readOnly">
               <bool>true</bool>
              </property>
-             <property name="html" >
-              <string>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
+             <property name="html">
+              <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
 p, li { white-space: pre-wrap; }
-&lt;/style>&lt;/head>&lt;body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
-&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;/p>&lt;/body>&lt;/html></string>
+hr { height: 1px; border-width: 0; }
+li.unchecked::marker { content: &quot;\2610&quot;; }
+li.checked::marker { content: &quot;\2612&quot;; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu Sans'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:9pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
              </property>
-             <property name="textInteractionFlags" >
+             <property name="textInteractionFlags">
               <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
              </property>
             </widget>
@@ -64,8 +68,8 @@ p, li { white-space: pre-wrap; }
          </widget>
         </item>
         <item>
-         <widget class="QPushButton" name="info_trace_clear" >
-          <property name="text" >
+         <widget class="QPushButton" name="info_trace_clear">
+          <property name="text">
            <string>clear trace resume</string>
           </property>
          </widget>
@@ -73,33 +77,23 @@ p, li { white-space: pre-wrap; }
        </layout>
       </item>
       <item>
-       <layout class="QVBoxLayout" name="verticalLayout_4" >
-        <property name="rightMargin" >
+       <layout class="QVBoxLayout" name="verticalLayout_4">
+        <property name="rightMargin">
          <number>0</number>
         </property>
-        <property name="bottomMargin" >
+        <property name="bottomMargin">
          <number>0</number>
         </property>
         <item>
-         <widget class="QGroupBox" name="info_selection" >
-          <property name="title" >
+         <widget class="QGroupBox" name="info_selection">
+          <property name="title">
            <string>Selection Informations</string>
           </property>
-          <layout class="QHBoxLayout" name="horizontalLayout_4" >
+          <layout class="QHBoxLayout" name="horizontalLayout_4">
            <item>
-            <widget class="QTextEdit" name="info_selection_text" >
-             <property name="readOnly" >
-              <bool>true</bool>
-             </property>
-             <property name="html" >
-              <string>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
-p, li { white-space: pre-wrap; }
-&lt;/style>&lt;/head>&lt;body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;">
-&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;/p>&lt;/body>&lt;/html></string>
-             </property>
-             <property name="textInteractionFlags" >
-              <set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
+            <widget class="QTabWidget" name="info_selection_tab">
+             <property name="currentIndex">
+              <number>-1</number>
              </property>
             </widget>
            </item>
@@ -107,8 +101,8 @@ p, li { white-space: pre-wrap; }
          </widget>
         </item>
         <item>
-         <widget class="QPushButton" name="pushButton" >
-          <property name="text" >
+         <widget class="QPushButton" name="pushButton">
+          <property name="text">
            <string>clear informations</string>
           </property>
          </widget>
@@ -121,7 +115,7 @@ p, li { white-space: pre-wrap; }
   </widget>
  </widget>
  <resources>
-  <include location="vite.qrc" />
+  <include location="vite.qrc"/>
  </resources>
  <connections>
   <connection>
@@ -130,31 +124,15 @@ p, li { white-space: pre-wrap; }
    <receiver>info_trace_text</receiver>
    <slot>clear()</slot>
    <hints>
-    <hint type="sourcelabel" >
+    <hint type="sourcelabel">
      <x>47</x>
      <y>217</y>
     </hint>
-    <hint type="destinationlabel" >
+    <hint type="destinationlabel">
      <x>152</x>
      <y>120</y>
     </hint>
    </hints>
   </connection>
-  <connection>
-   <sender>pushButton</sender>
-   <signal>clicked()</signal>
-   <receiver>info_selection_text</receiver>
-   <slot>clear()</slot>
-   <hints>
-    <hint type="sourcelabel" >
-     <x>369</x>
-     <y>217</y>
-    </hint>
-    <hint type="destinationlabel" >
-     <x>372</x>
-     <y>164</y>
-    </hint>
-   </hints>
-  </connection>
  </connections>
 </ui>
-- 
GitLab


From 5de2883ed62fe974720b04bfd414b4af935f48f8 Mon Sep 17 00:00:00 2001
From: Ordronneau Camille <camille.ordronneau@inria.fr>
Date: Fri, 24 May 2024 16:51:24 +0200
Subject: [PATCH 5/5] Change Interface.hpp interface

---
 src/core/Core.hpp                   | 15 +++++++++++
 src/interface/Interface.hpp         |  6 +++++
 src/interface/Interface_graphic.cpp | 42 ++++++++++++++++++++++++-----
 src/interface/Interface_graphic.hpp | 14 +++++++++-
 4 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/src/core/Core.hpp b/src/core/Core.hpp
index ce5a564b..4971b4cc 100644
--- a/src/core/Core.hpp
+++ b/src/core/Core.hpp
@@ -451,6 +451,21 @@ public:
     void selection_information(const std::string &) const override {
     }
 
+    /*!
+     * \brief Only use in graphic interface.
+     */
+    void selection_information_clear() const override { }
+
+    /*!
+     * \brief Only use in graphic interface.
+     */
+    void selection_information_show() const override { }
+
+    /*!
+     * \brief Only use in graphic interface.
+     */
+    virtual void selection_information_new_tab(const std::string &) const override { }
+
     /*!
      *\brief Set the minimum for export
      *\param d The double.
diff --git a/src/interface/Interface.hpp b/src/interface/Interface.hpp
index 05908b55..98a38026 100644
--- a/src/interface/Interface.hpp
+++ b/src/interface/Interface.hpp
@@ -76,6 +76,12 @@ public:
      */
     virtual void information(const std::string &) const = 0;
 
+    virtual void selection_information_clear() const = 0;
+
+    virtual void selection_information_show() const = 0;
+
+    virtual void selection_information_new_tab(const std::string &) const = 0;
+
     /*!
      *\arg string : the string to be displayed.
      *\brief The function takes strings and/or numbers then displayed it in the entity informative text area in the info window (use in graphic interface).
diff --git a/src/interface/Interface_graphic.cpp b/src/interface/Interface_graphic.cpp
index 1db14b05..6893fedf 100644
--- a/src/interface/Interface_graphic.cpp
+++ b/src/interface/Interface_graphic.cpp
@@ -52,6 +52,7 @@
 #include <list>
 /* -- */
 #include <QObject>
+#include <QWidget>
 #include <QtUiTools>/* for the run-time loading .ui file */
 #include <QCloseEvent>
 #include <QDir>
@@ -219,7 +220,7 @@ void Interface_graphic::load_windows() {
 
     CKFP(_ui_fullscreen_menu = this->findChild<QAction *>(QStringLiteral("fullscreen")), "Cannot find the fullscreen menu in the .ui file");
     CKFP(_ui_info_trace_text = _ui_info_window->findChild<QTextEdit *>(QStringLiteral("info_trace_text")), "Cannot find the info_trace_text QTextEdit widget in the .ui file");
-    CKFP(_ui_info_selection_text = _ui_info_window->findChild<QTextEdit *>(QStringLiteral("info_selection_text")), "Cannot find the info_selection_text QTextEdit widget in the .ui file");
+    CKFP(_ui_info_selection_tabs = _ui_info_window->findChild<QTabWidget *>(QStringLiteral("info_selection_tab")), "Cannot find the info_selection_tab QTabWidget widget in the .ui file");
     CKFP(_ui_toolbar = this->findChild<QToolBar *>(QStringLiteral("toolBar")), "Cannot find the tool bar in the .ui file");
 
     CKFP(_ui_x_scroll = this->findChild<QScrollBar *>(QStringLiteral("x_scroll")), "Cannot find the horizontal scroll bar in the .ui file");
@@ -304,15 +305,42 @@ void Interface_graphic::information(const string &s) const {
  *
  **********************************/
 
-void Interface_graphic::selection_information(const string &s) const {
-    QString buf = QString::fromStdString(s);
-    _ui_info_selection_text->clear(); /* Clear the current text (if exists) */
-    _ui_info_selection_text->insertHtml(QStringLiteral("<font color='blue'>") + buf + QStringLiteral("</font>"));
-    _ui_info_selection_text->moveCursor(QTextCursor::Start); /* Insert the new text on the begin */
+void Interface_graphic::selection_information_clear() const {
+    _ui_info_selection_tabs->clear(); /* Remove all tabs in the QTabWidget*/
+}
 
+void Interface_graphic::selection_information_show() const {
     _ui_info_window->show(); /* show info_window */
 }
 
+void Interface_graphic::selection_information_new_tab(const string &s) const {
+    QWidget *tab = new QWidget(_ui_info_selection_tabs);
+    _ui_info_selection_tabs->addTab(tab, QString::fromStdString(s));
+}
+
+void Interface_graphic::selection_information(const string &s) const {
+    const int tab_number = _ui_info_selection_tabs->count();
+    if (tab_number) {
+
+        QString buf = QString::fromStdString(s);
+
+        QVBoxLayout *layout = new QVBoxLayout(_ui_info_selection_tabs->widget(tab_number - 1)); /*Make the text box resize when window is resized*/
+
+        QTextEdit *text_widget = new QTextEdit();
+
+        text_widget->setReadOnly(true);
+        text_widget->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
+
+        text_widget->insertHtml(QStringLiteral("<font color='blue'>") + buf + QStringLiteral("</font>"));
+        text_widget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+        text_widget->moveCursor(QTextCursor::Start); /* Insert the new text on the begin */
+
+        layout->addWidget(text_widget);
+        layout->setEnabled(true);
+        layout->setContentsMargins(0, 0, 0, 0);
+    }
+}
+
 /***********************************
  *
  * Tool functions.
@@ -675,7 +703,7 @@ void Interface_graphic::on_close_triggered() {
      * Clear the informative window texts and hide it.
      */
     _ui_info_trace_text->clear(); /* Clear the current text (if exists) */
-    _ui_info_selection_text->clear(); /* Clear the current text (if exists) */
+    _ui_info_selection_tabs->clear(); /* Clear the current text (if exists) */
     _ui_info_window->hide(); /* Hide the informative window */
 
     if (_ui_settings) {
diff --git a/src/interface/Interface_graphic.hpp b/src/interface/Interface_graphic.hpp
index 22270edd..fdb187c2 100644
--- a/src/interface/Interface_graphic.hpp
+++ b/src/interface/Interface_graphic.hpp
@@ -235,7 +235,7 @@ protected:
     /*!
      * \brief Text area which informs the user about the selected entity information.
      */
-    QTextEdit *_ui_info_selection_text;
+    QTabWidget *_ui_info_selection_tabs;
 
     /*!
      * \brief The menu where recent files are printed
@@ -364,6 +364,18 @@ public:
      *
      **********************************/
 
+    /*!
+     * \brief Clear the entity tabs in the info window.
+     */
+    void selection_information_clear() const override;
+
+    /*!
+     * \brief Show the info window.
+     */
+    void selection_information_show() const override;
+
+    virtual void selection_information_new_tab(const std::string &) const override;
+
     /*!
      * \brief The function takes strings and/or numbers then displayed it in the entity informative text area in the info window.
      * \param string The string to be displayed.
-- 
GitLab