Sélectionner un nœud du graphe et afficher la fiche de l’entité #65

Closed
opened 2026-07-21 17:55:49 +02:00 by fy59 · 0 comments
Owner

Sélectionner un nœud du graphe et afficher la fiche de l’entité

Contexte

La vue graphique permet désormais :

  • l’affichage des entités et des relations ;
  • le zoom avec Ctrl + défilement ;
  • le déplacement du canvas avec Shift + glisser ;
  • le déplacement individuel des nœuds avec un glisser simple.

Les nœuds sont visibles et manipulables, mais il n’est pas encore possible de sélectionner une entité ni de consulter ses informations depuis le graphe.

Objectif

Permettre à l’utilisateur de sélectionner un nœud par un clic simple et d’afficher les informations principales de l’entité correspondante.

La sélection doit rester entièrement en lecture seule dans ce ticket.

Interaction attendue

Clic simple sur un nœud  → sélectionner l’entité
Clic simple dans le vide → désélectionner
Glisser sur un nœud      → déplacer le nœud sans ouvrir la fiche
Shift + glisser          → déplacer le canvas
Ctrl + défilement        → zoom

Un clic ne doit être considéré comme une sélection que lorsqu’aucun déplacement significatif n’a été détecté.

Architecture attendue

InvestigationGraphView

InvestigationGraphView doit :

  • détecter le nœud situé sous le pointeur ;
  • conserver le nœud actuellement sélectionné ;
  • dessiner ce nœud avec un état visuel distinct ;
  • émettre un callback lors d’un changement de sélection ;
  • ne jamais posséder ni libérer l’EntityRecord.

Workspace

Workspace doit :

  • recevoir l’entité sélectionnée ;
  • afficher ses informations sans prendre possession du modèle ;
  • copier immédiatement les textes dans les widgets GTK ;
  • conserver le graphe visible pendant la consultation de la fiche ;
  • restaurer un état neutre lors de la désélection.

Application et MainWindow

Application reste propriétaire du graphe.

MainWindow peut continuer à jouer un rôle de relais si nécessaire, mais aucune logique métier ne doit y être ajoutée.

API publique proposée

Ajouter dans investigation_graph_view.h :

typedef void (*InvestigationGraphViewSelectionCallback)(
    const EntityRecord *entity_record,
    gpointer user_data
);

void investigation_graph_view_set_selection_callback(
    InvestigationGraphView *graph_view,
    InvestigationGraphViewSelectionCallback callback,
    gpointer user_data
);

const EntityRecord *investigation_graph_view_get_selected_entity(
    const InvestigationGraphView *graph_view
);

void investigation_graph_view_clear_selection(
    InvestigationGraphView *graph_view
);

Le callback reçoit un pointeur emprunté au graphe.

Il doit recevoir NULL lors d’une désélection.

État privé proposé

La vue peut conserver :

InvestigationGraphNodeLayout *selected_node;

InvestigationGraphViewSelectionCallback selection_callback;
gpointer selection_user_data;

selected_node est emprunté à la disposition privée de la vue.

Il doit être remis à NULL lors :

  • du changement de graphe ;
  • de investigation_graph_view_clear() ;
  • de investigation_graph_view_reset_layout() si la disposition est reconstruite ;
  • de la libération de la vue.

Détection du clic

Le geste de glisser actuel peut être complété par un GtkGestureClick ou par une détection fiable entre début et fin du geste.

Le comportement doit distinguer :

  • un clic bref sans déplacement ;
  • un déplacement individuel de nœud ;
  • un déplacement global du canvas.

Une petite tolérance de mouvement peut être utilisée afin d’éviter qu’un tremblement du pointeur transforme un clic en déplacement.

Priorité des gestes

L’ordre de priorité attendu est :

  1. Shift + glisser : déplacement du canvas ;
  2. glisser simple avec mouvement : déplacement du nœud ;
  3. clic simple sur un nœud : sélection ;
  4. clic simple dans le vide : désélection.

Un glisser terminé sur un nœud ne doit pas déclencher une sélection accidentelle en fin de geste.

Rendu de la sélection

Le nœud sélectionné doit rester lisible et être clairement identifiable.

Une différence visuelle légère suffit, par exemple :

  • contour plus épais ;
  • contour plus lumineux ;
  • fond légèrement différent.

Les couleurs ne doivent pas être codées en fonction du type métier dans ce ticket.

Le nœud sélectionné doit être dessiné au premier plan lorsque plusieurs nœuds se chevauchent.

Fiche de l’entité

La fiche doit afficher au minimum :

  • libellé ;
  • valeur ;
  • type métier ;
  • description ;
  • niveau de confiance ;
  • statut ;
  • date de création ;
  • date de modification ;
  • UUID.

Les champs facultatifs absents doivent afficher un texte de remplacement clair.

Le niveau de confiance doit être affiché sous une forme lisible, par exemple :

Confiance : 85 %

Le statut doit être converti en texte utilisateur :

  • active → Active ;
  • archived → Archivée ;
  • deleted → Supprimée ;
  • valeur inconnue → Inconnu.

Intégration dans Workspace

La fiche ne doit pas remplacer définitivement le canvas.

Disposition recommandée :

  • utiliser un GtkPaned horizontal ;
  • conserver le graphe à gauche ;
  • afficher un panneau de détails à droite ;
  • masquer ou réduire le panneau lorsqu’aucune entité n’est sélectionnée.

Le panneau de détails peut utiliser un GtkScrolledWindow afin de rester utilisable dans une petite fenêtre.

Le comportement existant des pages de chargement et d’erreur doit être conservé.

Gestion de la mémoire

  • Application possède le InvestigationGraphModel.
  • InvestigationGraphView emprunte le graphe et les EntityRecord.
  • Workspace ne possède pas l’entité sélectionnée.
  • Les textes de la fiche sont copiés par GTK.
  • Le callback et son user_data sont empruntés.
  • Aucun pointeur vers une ancienne entité ne doit subsister après un changement de graphe.
  • investigation_graph_view_free() doit détacher le callback.

Gestion des erreurs

Une entité invalide ou absente ne doit jamais provoquer de crash.

En cas de sélection incohérente :

  • désélectionner proprement ;
  • masquer la fiche ;
  • conserver le graphe utilisable.

Hors périmètre

Ce ticket n’inclut pas :

  • modification de l’entité ;
  • suppression de l’entité ;
  • ajout ou suppression de relation ;
  • double-clic ;
  • menu contextuel ;
  • sélection multiple ;
  • édition en place ;
  • persistance de la sélection ;
  • centrage automatique sur l’entité ;
  • ouverture d’une preuve liée ;
  • persistance des positions des nœuds.

Ces fonctions feront l’objet de tickets séparés.

Critères d’acceptation

  • Un clic simple sur un nœud sélectionne l’entité correspondante.
  • Le nœud sélectionné possède un rendu visuel distinct.
  • Un clic dans le vide désélectionne l’entité.
  • Un glisser de nœud ne déclenche pas de sélection accidentelle.
  • Shift + glisser continue de déplacer le canvas.
  • Le zoom continue de fonctionner.
  • La fiche affiche les informations principales de l’entité.
  • Les champs facultatifs absents sont gérés proprement.
  • Le canvas reste visible pendant l’affichage de la fiche.
  • Le changement de graphe supprime l’ancienne sélection.
  • investigation_graph_view_clear() supprime la sélection.
  • Aucun composant de vue ne libère l’EntityRecord.
  • Aucun avertissement GTK ou Cairo n’apparaît.
  • make clean && make réussit avec -Werror -Wpedantic.
  • make test réussit.
  • git diff --check ne signale aucune erreur.

Plan d’implémentation conseillé

  1. Ajouter l’état de sélection dans InvestigationGraphView.
  2. Ajouter l’API du callback de sélection.
  3. Distinguer clic et glisser.
  4. Détecter le nœud sous le clic.
  5. Ajouter le rendu visuel du nœud sélectionné.
  6. Créer le panneau de détails dans Workspace.
  7. Relier le callback de la vue au panneau.
  8. Gérer la désélection.
  9. Nettoyer la sélection lors des changements de graphe.
  10. Tester les interactions combinées.

Validation manuelle

  1. Ouvrir une enquête contenant plusieurs entités.
  2. Cliquer sur chaque nœud.
  3. Vérifier le contenu de la fiche.
  4. Cliquer dans le vide.
  5. Déplacer un nœud.
  6. Vérifier qu’aucune fiche ne s’ouvre accidentellement.
  7. Zoomer puis sélectionner un nœud.
  8. Déplacer le canvas puis sélectionner un nœud.
  9. Ouvrir une autre enquête.
  10. Fermer l’application après plusieurs sélections.
# Sélectionner un nœud du graphe et afficher la fiche de l’entité ## Contexte La vue graphique permet désormais : - l’affichage des entités et des relations ; - le zoom avec `Ctrl` + défilement ; - le déplacement du canvas avec `Shift` + glisser ; - le déplacement individuel des nœuds avec un glisser simple. Les nœuds sont visibles et manipulables, mais il n’est pas encore possible de sélectionner une entité ni de consulter ses informations depuis le graphe. ## Objectif Permettre à l’utilisateur de sélectionner un nœud par un clic simple et d’afficher les informations principales de l’entité correspondante. La sélection doit rester entièrement en lecture seule dans ce ticket. ## Interaction attendue ```text Clic simple sur un nœud → sélectionner l’entité Clic simple dans le vide → désélectionner Glisser sur un nœud → déplacer le nœud sans ouvrir la fiche Shift + glisser → déplacer le canvas Ctrl + défilement → zoom ``` Un clic ne doit être considéré comme une sélection que lorsqu’aucun déplacement significatif n’a été détecté. ## Architecture attendue ### InvestigationGraphView `InvestigationGraphView` doit : - détecter le nœud situé sous le pointeur ; - conserver le nœud actuellement sélectionné ; - dessiner ce nœud avec un état visuel distinct ; - émettre un callback lors d’un changement de sélection ; - ne jamais posséder ni libérer l’`EntityRecord`. ### Workspace `Workspace` doit : - recevoir l’entité sélectionnée ; - afficher ses informations sans prendre possession du modèle ; - copier immédiatement les textes dans les widgets GTK ; - conserver le graphe visible pendant la consultation de la fiche ; - restaurer un état neutre lors de la désélection. ### Application et MainWindow `Application` reste propriétaire du graphe. `MainWindow` peut continuer à jouer un rôle de relais si nécessaire, mais aucune logique métier ne doit y être ajoutée. ## API publique proposée Ajouter dans `investigation_graph_view.h` : ```c typedef void (*InvestigationGraphViewSelectionCallback)( const EntityRecord *entity_record, gpointer user_data ); void investigation_graph_view_set_selection_callback( InvestigationGraphView *graph_view, InvestigationGraphViewSelectionCallback callback, gpointer user_data ); const EntityRecord *investigation_graph_view_get_selected_entity( const InvestigationGraphView *graph_view ); void investigation_graph_view_clear_selection( InvestigationGraphView *graph_view ); ``` Le callback reçoit un pointeur emprunté au graphe. Il doit recevoir `NULL` lors d’une désélection. ## État privé proposé La vue peut conserver : ```c InvestigationGraphNodeLayout *selected_node; InvestigationGraphViewSelectionCallback selection_callback; gpointer selection_user_data; ``` `selected_node` est emprunté à la disposition privée de la vue. Il doit être remis à `NULL` lors : - du changement de graphe ; - de `investigation_graph_view_clear()` ; - de `investigation_graph_view_reset_layout()` si la disposition est reconstruite ; - de la libération de la vue. ## Détection du clic Le geste de glisser actuel peut être complété par un `GtkGestureClick` ou par une détection fiable entre début et fin du geste. Le comportement doit distinguer : - un clic bref sans déplacement ; - un déplacement individuel de nœud ; - un déplacement global du canvas. Une petite tolérance de mouvement peut être utilisée afin d’éviter qu’un tremblement du pointeur transforme un clic en déplacement. ## Priorité des gestes L’ordre de priorité attendu est : 1. `Shift` + glisser : déplacement du canvas ; 2. glisser simple avec mouvement : déplacement du nœud ; 3. clic simple sur un nœud : sélection ; 4. clic simple dans le vide : désélection. Un glisser terminé sur un nœud ne doit pas déclencher une sélection accidentelle en fin de geste. ## Rendu de la sélection Le nœud sélectionné doit rester lisible et être clairement identifiable. Une différence visuelle légère suffit, par exemple : - contour plus épais ; - contour plus lumineux ; - fond légèrement différent. Les couleurs ne doivent pas être codées en fonction du type métier dans ce ticket. Le nœud sélectionné doit être dessiné au premier plan lorsque plusieurs nœuds se chevauchent. ## Fiche de l’entité La fiche doit afficher au minimum : - libellé ; - valeur ; - type métier ; - description ; - niveau de confiance ; - statut ; - date de création ; - date de modification ; - UUID. Les champs facultatifs absents doivent afficher un texte de remplacement clair. Le niveau de confiance doit être affiché sous une forme lisible, par exemple : ```text Confiance : 85 % ``` Le statut doit être converti en texte utilisateur : - active → Active ; - archived → Archivée ; - deleted → Supprimée ; - valeur inconnue → Inconnu. ## Intégration dans Workspace La fiche ne doit pas remplacer définitivement le canvas. Disposition recommandée : - utiliser un `GtkPaned` horizontal ; - conserver le graphe à gauche ; - afficher un panneau de détails à droite ; - masquer ou réduire le panneau lorsqu’aucune entité n’est sélectionnée. Le panneau de détails peut utiliser un `GtkScrolledWindow` afin de rester utilisable dans une petite fenêtre. Le comportement existant des pages de chargement et d’erreur doit être conservé. ## Gestion de la mémoire - `Application` possède le `InvestigationGraphModel`. - `InvestigationGraphView` emprunte le graphe et les `EntityRecord`. - `Workspace` ne possède pas l’entité sélectionnée. - Les textes de la fiche sont copiés par GTK. - Le callback et son `user_data` sont empruntés. - Aucun pointeur vers une ancienne entité ne doit subsister après un changement de graphe. - `investigation_graph_view_free()` doit détacher le callback. ## Gestion des erreurs Une entité invalide ou absente ne doit jamais provoquer de crash. En cas de sélection incohérente : - désélectionner proprement ; - masquer la fiche ; - conserver le graphe utilisable. ## Hors périmètre Ce ticket n’inclut pas : - modification de l’entité ; - suppression de l’entité ; - ajout ou suppression de relation ; - double-clic ; - menu contextuel ; - sélection multiple ; - édition en place ; - persistance de la sélection ; - centrage automatique sur l’entité ; - ouverture d’une preuve liée ; - persistance des positions des nœuds. Ces fonctions feront l’objet de tickets séparés. ## Critères d’acceptation - [x] Un clic simple sur un nœud sélectionne l’entité correspondante. - [x] Le nœud sélectionné possède un rendu visuel distinct. - [x] Un clic dans le vide désélectionne l’entité. - [x] Un glisser de nœud ne déclenche pas de sélection accidentelle. - [x] `Shift` + glisser continue de déplacer le canvas. - [x] Le zoom continue de fonctionner. - [x] La fiche affiche les informations principales de l’entité. - [x] Les champs facultatifs absents sont gérés proprement. - [x] Le canvas reste visible pendant l’affichage de la fiche. - [x] Le changement de graphe supprime l’ancienne sélection. - [x] `investigation_graph_view_clear()` supprime la sélection. - [x] Aucun composant de vue ne libère l’`EntityRecord`. - [x] Aucun avertissement GTK ou Cairo n’apparaît. - [x] `make clean && make` réussit avec `-Werror -Wpedantic`. - [x] `make test` réussit. - [x] `git diff --check` ne signale aucune erreur. ## Plan d’implémentation conseillé 1. Ajouter l’état de sélection dans `InvestigationGraphView`. 2. Ajouter l’API du callback de sélection. 3. Distinguer clic et glisser. 4. Détecter le nœud sous le clic. 5. Ajouter le rendu visuel du nœud sélectionné. 6. Créer le panneau de détails dans `Workspace`. 7. Relier le callback de la vue au panneau. 8. Gérer la désélection. 9. Nettoyer la sélection lors des changements de graphe. 10. Tester les interactions combinées. ## Validation manuelle 1. Ouvrir une enquête contenant plusieurs entités. 2. Cliquer sur chaque nœud. 3. Vérifier le contenu de la fiche. 4. Cliquer dans le vide. 5. Déplacer un nœud. 6. Vérifier qu’aucune fiche ne s’ouvre accidentellement. 7. Zoomer puis sélectionner un nœud. 8. Déplacer le canvas puis sélectionner un nœud. 9. Ouvrir une autre enquête. 10. Fermer l’application après plusieurs sélections.
fy59 closed this issue 2026-07-21 21:39:48 +02:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: fy59/labfy-investigation#65
No description provided.