diff --git a/src/src/twisk/modele/MondeIG.java b/src/src/twisk/modele/MondeIG.java index 1ef1609dd197dfc6fb155e560772b6cd5649d4db..8886a5125f72c2cba358a435361c03798f6fdd4e 100644 --- a/src/src/twisk/modele/MondeIG.java +++ b/src/src/twisk/modele/MondeIG.java @@ -105,6 +105,10 @@ public class MondeIG implements Iterable<EtapeIG>, Observable { throw new ArcException("Impossible de créer un arc: le point d'arrivée est déjà utilisé comme destination d'un autre arc"); } } + // Contrainte 7: Vérifier que l'ajout de cet arc ne crée pas de cycle + if (creeraitUnCycle(pt1.getEtape(), pt2.getEtape())) { + throw new ArcException("Impossible de créer un arc: cela créerait un cycle dans le graphe"); + } // Toutes les contraintes sont satisfaites, on peut ajouter l'arc ArcIG arc = new LigneDroiteIG(pt1, pt2); @@ -701,6 +705,58 @@ public class MondeIG implements Iterable<EtapeIG>, Observable { return (ActiviteIG) etape; } + /** + * Vérifie si l'ajout d'un arc entre deux étapes créerait un cycle dans le graphe + * @param etapeSource l'étape source + * @param etapeDestination l'étape destination + * @return true si l'ajout créerait un cycle, false sinon + */ + private boolean creeraitUnCycle(EtapeIG etapeSource, EtapeIG etapeDestination) { + // Si on peut atteindre l'étape source à partir de l'étape destination, + // alors ajouter un arc de source vers destination créerait un cycle + return peutAtteindre(etapeDestination, etapeSource); + } + + /** + * Vérifie si on peut atteindre une étape cible à partir d'une étape source + * en suivant les arcs existants + * @param etapeSource l'étape source + * @param etapeCible l'étape cible + * @return true si on peut atteindre l'étape cible, false sinon + */ + private boolean peutAtteindre(EtapeIG etapeSource, EtapeIG etapeCible) { + // Ensemble des étapes déjà visitées pour éviter les boucles infinies + Set<String> etapesVisitees = new HashSet<>(); + + // File pour le parcours en largeur + Queue<EtapeIG> file = new LinkedList<>(); + file.add(etapeSource); + + while (!file.isEmpty()) { + EtapeIG etapeCourante = file.poll(); + + // Si on a atteint l'étape cible, retourner true + if (etapeCourante.equals(etapeCible)) { + return true; + } + + // Marquer l'étape comme visitée + etapesVisitees.add(etapeCourante.getIdentifiant()); + + // Ajouter toutes les étapes successeurs à la file + for (ArcIG arc : arcs) { + if (arc.getP1().getEtape().equals(etapeCourante)) { + EtapeIG etapeSuccesseur = arc.getP2().getEtape(); + if (!etapesVisitees.contains(etapeSuccesseur.getIdentifiant())) { + file.add(etapeSuccesseur); + } + } + } + } + + // Si on a parcouru tout le graphe sans trouver l'étape cible, retourner false + return false; + } } diff --git a/src/src/twisk/ressources/css/style-colore.css b/src/src/twisk/ressources/css/style-colore.css index b5f5201ce15157836b8bd6418b759c568c9046d4..c7f91c2efa186116e4f80479d4ba150a8a093fee 100644 --- a/src/src/twisk/ressources/css/style-colore.css +++ b/src/src/twisk/ressources/css/style-colore.css @@ -1,12 +1,13 @@ /* Styles généraux */ .root { - -fx-font-family: 'Comic Sans MS', cursive; - -fx-background-color: #f0f8ff; + -fx-font-family: 'Segoe UI', 'Roboto', sans-serif; + -fx-background-color: #f0f5fa; + -fx-background: linear-gradient(to bottom right, #e8f5fd, #f0e6ff); } /* Style pour VueMondeIG */ .monde { - -fx-background-color: linear-gradient(to bottom right, #e6f7ff, #f0e6ff); + -fx-background-color: linear-gradient(to bottom right, #e8eef7, #f5e8f7); -fx-padding: 10px; } @@ -16,134 +17,163 @@ } .activite-rectangle { - -fx-fill: linear-gradient(to bottom, #ffffff, #f0f0ff); - -fx-stroke: #9966cc; - -fx-stroke-width: 3; - -fx-arc-width: 20; - -fx-arc-height: 20; - -fx-effect: dropshadow(three-pass-box, rgba(153,102,204,0.5), 10, 0, 0, 5); + -fx-fill: linear-gradient(to bottom, #ffffff, #f8f8ff); + -fx-stroke: #5b6abf; + -fx-stroke-width: 2; + -fx-arc-width: 12; + -fx-arc-height: 12; + -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.2), 5, 0, 0, 2); } /* Style pour le titre de l'activité */ .titre-activite { - -fx-font-size: 16px; + -fx-font-size: 14px; -fx-font-weight: bold; - -fx-text-fill: #6600cc; + -fx-text-fill: #2c3e50; -fx-padding: 8px; - -fx-background-color: linear-gradient(to right, #e6ccff, #ccccff); - -fx-background-radius: 15 15 0 0; + -fx-background-color: linear-gradient(to right, #d4e4fc, #e0d4fc); + -fx-background-radius: 8 8 0 0; } -/* Modifications pour la zone des clients */ +/* Style pour la zone des clients */ .zone-clients { -fx-background-color: #ffffff; - -fx-border-color: #cc99ff; - -fx-border-width: 2px; - -fx-border-radius: 0 0 15 15; - -fx-background-radius: 0 0 15 15; + -fx-border-color: #b8d1f3; + -fx-border-width: 1px; + -fx-border-radius: 0 0 8 8; + -fx-background-radius: 0 0 8 8; -fx-padding: 8px; -fx-min-height: 30px; - -fx-font-size: 12px; + -fx-text-fill: #2c3e50; } -/* Modifications pour la zone des paramètres */ +/* Style pour la zone des paramètres */ .zone-parametres { - -fx-background-color: #f5f0ff; - -fx-border-color: #cc99ff; - -fx-border-width: 2px; - -fx-border-radius: 0 0 15 15; - -fx-background-radius: 0 0 15 15; + -fx-background-color: #f5f9ff; + -fx-border-color: #b8d1f3; + -fx-border-width: 1px; + -fx-border-radius: 0 0 8 8; + -fx-background-radius: 0 0 8 8; -fx-padding: 8px; - -fx-font-size: 10px; - -fx-text-fill: #6600cc; + -fx-font-size: 11px; + -fx-text-fill: #546e7a; } - /* Style pour la barre d'outils */ .outils { - -fx-background-color: linear-gradient(to right, #cc99ff, #9966cc); - -fx-padding: 12px; - -fx-spacing: 15px; + -fx-background-color: linear-gradient(to right, #3498db, #9b59b6); + -fx-padding: 10px; + -fx-spacing: 10px; } /* Style pour les boutons */ .bouton { - -fx-background-color: #ff66cc; + -fx-background-color: #5e72e4; -fx-text-fill: white; -fx-font-weight: bold; - -fx-padding: 10px 20px; - -fx-background-radius: 20px; + -fx-padding: 8px 15px; + -fx-background-radius: 4px; -fx-cursor: hand; - -fx-effect: dropshadow(three-pass-box, rgba(255,102,204,0.5), 5, 0, 0, 2); + -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.2), 3, 0, 0, 1); } .bouton:hover { - -fx-background-color: #ff33cc; - -fx-effect: dropshadow(three-pass-box, rgba(255,102,204,0.8), 8, 0, 0, 3); + -fx-background-color: #7795f8; } .bouton:pressed { - -fx-background-color: #cc0099; - -fx-effect: dropshadow(three-pass-box, rgba(255,102,204,0.3), 3, 0, 0, 1); + -fx-background-color: #324cdd; } /* Style pour les points de contrôle */ .point-controle { - -fx-fill: #ff99cc; - -fx-stroke: #cc0099; - -fx-stroke-width: 2; + -fx-fill: #5e72e4; + -fx-stroke: #324cdd; + -fx-stroke-width: 1; -fx-cursor: hand; } .point-controle:hover { - -fx-fill: #ff66cc; - -fx-effect: dropshadow(three-pass-box, rgba(255,102,204,0.8), 5, 0, 0, 0); - -fx-scale-x: 1.2; - -fx-scale-y: 1.2; + -fx-fill: #7795f8; + -fx-effect: dropshadow(three-pass-box, rgba(94,114,228,0.5), 3, 0, 0, 0); } /* Style pour les arcs */ .arc-ligne { - -fx-stroke: #9966cc; - -fx-stroke-width: 3; - -fx-stroke-dash-array: 10 5; - -fx-effect: dropshadow(three-pass-box, rgba(153,102,204,0.5), 3, 0, 0, 0); + -fx-stroke: linear-gradient(#5e72e4, #11cdef); + -fx-stroke-width: 2; } .arc-fleche { - -fx-fill: #9966cc; - -fx-stroke: #6600cc; - -fx-stroke-width: 2; + -fx-fill: #5e72e4; + -fx-stroke: #324cdd; + -fx-stroke-width: 1; } /* Style pour les étapes sélectionnées */ .etape-selectionnee { - -fx-effect: dropshadow(three-pass-box, #ff33cc, 15, 0, 0, 0); + -fx-effect: dropshadow(three-pass-box, #fb6340, 8, 0, 0, 0); } .etape-selectionnee .activite-rectangle { - -fx-stroke: #ff33cc; - -fx-stroke-width: 4; + -fx-stroke: #fb6340; + -fx-stroke-width: 3; } /* Style pour les entrées */ .etape-entree .activite-rectangle { - -fx-fill: linear-gradient(to bottom, #ffffff, #e6ffe6); - -fx-stroke: #66cc66; + -fx-fill: linear-gradient(to bottom, #ffffff, #e8f5e9); + -fx-stroke: #2dce89; } .etape-entree .titre-activite { - -fx-text-fill: #006600; - -fx-background-color: linear-gradient(to right, #ccffcc, #99ff99); + -fx-text-fill: #1e8449; + -fx-background-color: linear-gradient(to right, #c8e6c9, #aee4bc); +} + +.etape-entree .zone-clients { + -fx-border-color: #a5d6a7; } /* Style pour les sorties */ .etape-sortie .activite-rectangle { - -fx-fill: linear-gradient(to bottom, #ffffff, #ffe6e6); - -fx-stroke: #cc6666; + -fx-fill: linear-gradient(to bottom, #ffffff, #ffebee); + -fx-stroke: #f5365c; } .etape-sortie .titre-activite { - -fx-text-fill: #660000; - -fx-background-color: linear-gradient(to right, #ffcccc, #ff9999); + -fx-text-fill: #b31217; + -fx-background-color: linear-gradient(to right, #ffcdd2, #f9a8b4); +} + +.etape-sortie .zone-clients { + -fx-border-color: #ef9a9a; +} + +/* Styles supplémentaires pour plus de couleurs */ +.activite:nth-child(3n+1) .activite-rectangle { + -fx-fill: linear-gradient(to bottom, #ffffff, #e3f2fd); + -fx-stroke: #11cdef; +} + +.activite:nth-child(3n+1) .titre-activite { + -fx-background-color: linear-gradient(to right, #bbdefb, #b3e5fc); +} + +.activite:nth-child(3n+2) .activite-rectangle { + -fx-fill: linear-gradient(to bottom, #ffffff, #fff8e1); + -fx-stroke: #ffd600; +} + +.activite:nth-child(3n+2) .titre-activite { + -fx-background-color: linear-gradient(to right, #ffecb3, #fff59d); +} + +.activite:nth-child(4n) .activite-rectangle { + -fx-fill: linear-gradient(to bottom, #ffffff, #f3e5f5); + -fx-stroke: #8e24aa; +} + +.activite:nth-child(4n) .titre-activite { + -fx-background-color: linear-gradient(to right, #e1bee7, #d1c4e9); }