arnaud.lewandowski@univ-littoral.fr il y a 3 ans
Parent
commit
a81d67ed8d
8 fichiers modifiés avec 194 ajouts et 2 suppressions
  1. 3 0
      README.md
  2. 1 1
      docs/TP1.md
  3. 1 1
      docs/TP4.md
  4. 29 0
      docs/TP5.md
  5. 39 0
      docs/TP7.md
  6. 64 0
      docs/TP8.md
  7. 57 0
      docs/TP9.md
  8. BIN
      docs/images/minipaint_09.png

+ 3 - 0
README.md

@@ -8,3 +8,6 @@ Cette application en JavaFX, permettant de dessiner des formes géométriques, v
 - [TP4 – On continue...](docs/TP4.md)
 - [TP4 – On continue...](docs/TP4.md)
 - [TP5 – Groupement de formes](docs/TP5.md)
 - [TP5 – Groupement de formes](docs/TP5.md)
 - [TP6 – Le patron Command](docs/TP6.md)
 - [TP6 – Le patron Command](docs/TP6.md)
+- [TP7 – Améliorations](docs/TP7.md)
+- [TP8 – Le retour de l'Observer](docs/TP8.md)
+- [TP9 – Changement de stratégie](docs/TP9.md)

+ 1 - 1
docs/TP1.md

@@ -4,7 +4,7 @@
 Dans cette première partie, nous allons nous familiariser avec le code de l’application, et en profiter pour découvrir un ou deux patrons de conception. 
 Dans cette première partie, nous allons nous familiariser avec le code de l’application, et en profiter pour découvrir un ou deux patrons de conception. 
 
 
 
 
-### 🔬 À la recherche des classes perdues...
+### 🗺 À la recherche des classes perdues...
 ---
 ---
 D’abord, importez le projet sous IntelliJ, Eclipse, ou un autre environnement de développement de votre choix. 
 D’abord, importez le projet sous IntelliJ, Eclipse, ou un autre environnement de développement de votre choix. 
 Les dépendances du projet sont gérées automatiquement grâce à Maven. Par curiosité, vous pouvez les identifier dans le fichier `pom.xml` :
 Les dépendances du projet sont gérées automatiquement grâce à Maven. Par curiosité, vous pouvez les identifier dans le fichier `pom.xml` :

+ 1 - 1
docs/TP4.md

@@ -35,7 +35,7 @@ Grâce à la sélection multiple, on peut donc appliquer des actions sur toutes
 
 
 >**🖥 TODO**
 >**🖥 TODO**
 >
 >
-> - Corrigez cela… 🩹
+> - Corrigez cela… 
 
 
 <br> 
 <br> 
 
 

+ 29 - 0
docs/TP5.md

@@ -14,4 +14,33 @@ Même s’il est possible de déplacer plusieurs formes à la fois (grâce à la
 
 
 <br>
 <br>
 
 
+### 🎀 Quelques améliorations
+---
+Vous avez sans doute remarqué qu'il reste quelques fonctionnements disgracieux : par exemple, si on souhaite créer une forme, et que le point de départ se trouve sur une forme déjà existante, celle-ci est déplacée en même temps que l'autre est créée. 
+
+>**🖥 TODO**
+>
+> - Faites en sorte que le déplacement soit désactivé lorsqu'une forme est en train d'être créée.
+
+<br>
+
+Une autre fonction intéressante serait de pouvoir mettre une forme au premier plan (devant les autres).
+
+>**🖥 TODO**
+>
+> - Implémentez cette fonctionnalité
+
+<br>
+
+#### 🏆 Bonus
+
+>**🖥 TODO**
+>
+> - On voudrait aussi pouvoir sélectionner plusieurs formes en délimitant une "zone" de sélection avec la souris (par un clic-drag-release)
+
+
+
+<br>
+
+
 [🔙 Retour](../README.md)
 [🔙 Retour](../README.md)

+ 39 - 0
docs/TP7.md

@@ -0,0 +1,39 @@
+# Minipaint 
+## TP7 – Améliorations
+
+### 🧬 Dupliquer une forme
+---
+On aimerait pouvoir dupliquer facilement la ou les formes sélectionnées. 
+
+>**🖥 TODO**
+>
+> - Identifiez le patron de création qui semble correspondre à ce besoin. 
+> - Implémentez le code nécessaire.
+
+<br>
+
+### 📝 Ajouter du texte sur une forme
+---
+On voudrait pouvoir ajouter du texte sur une forme sélectionnée. On ne veut pas en faire un attribut de la classe `ShapeAdapter`, car en général, seulement quelques formes seront concernées : inutile de « polluer » la classe avec cela. 
+
+Nous allons pour cela utiliser le patron *Décorateur* (lien vers la [vidéo qui en parle](https://www.youtube.com/watch?v=GCraGHx6gso&t=140s)). Ce patron permet d’ajouter de manière dynamique des informations sur certains objets. 
+
+
+>**🖥 TODO**
+>
+> - Etudiez le fonctionnement du patron, identifiez les classes concernées dans l’application, et faites les changements nécessaires. 
+> - On pourra ajouter un bouton dans la Toolbar permettant d’ajouter du texte sur la (ou les) forme(s) sélectionnée(s).
+
+<br> 
+
+### 🚧 Gestion des exceptions
+---
+>**🖥 TODO**
+>
+> - Si on cherche à ajouter du texte sur un groupe de formes, une exception doit être levée au niveau du décorateur. Cette exception sera capturée par la commande qui est à l’origine de l’action, et un message d’erreur doit être affiché. Si une commande provoque une exception, elle ne doit pas être ajoutée à la pile de commandes (l'historique pour le undo/redo).
+> - Étendre ce mécanisme d’exception à toutes les commandes. Si une commande rencontre une erreur (par exemple si aucune forme n’est sélectionnée), alors une exception doit être levée, et la commande ne sera pas ajoutée à l’historique. 
+> - Les messages d’erreur des exceptions seront affichés dans une nouvelle barre de statut.
+
+<br>
+
+[🔙 Retour](../README.md)

+ 64 - 0
docs/TP8.md

@@ -0,0 +1,64 @@
+# Minipaint 
+## TP8 – Le retour de l'Observer 
+
+### 💥 Encore de l’observer 
+---
+On l’aime vraiment bien, ce patron… En fait, il est tellement utile qu’on le retrouve partout, implémenté dans chaque recoin des API. Prenons encore un exemple. 
+
+Reprenons la fonctionnalité permettant d’ajouter du texte à une forme. Pour cela, dans le décorateur, on a ajouté un objet de type `Text` qui contient la chaine de caractères. On l’a positionné comme on a pu, et ensuite on a veillé à bien le déplacer en même temps que la forme lors des appels à la méthode offset.
+
+C’est bien, mais on aurait pu utiliser une fonctionnalité de l’API `javafx` qui est basée sur le patron *observer* : c’est la notion de *Binding*. En gros, cela permet de lier un attribut d’un objet à une propriété d’un autre objet. C’est-à-dire que la valeur du premier attribut sera automatiquement mise à jour lorsque l’autre attribut sera modifié. 
+
+Voyons comment utiliser cela. Tout d’abord, les propriétés qu’on veut « écouter » sont celles qui sont relatives au déplacement de la forme de base. 
+
+>**🖥 TODO**
+>
+> - On va les rendre accessibles en ajoutant deux méthodes à l’interface `IShape` :
+>
+		public ObservableValue translateXProperty();
+		public ObservableValue translateYProperty();
+	
+> - On va commencer par implémenter ces méthodes uniquement dans la classe `ShapeAdapter`. L’implémentation consiste simplement à retourner le résultat de l’appel à `translateXProperty()` et `translateYProperty()` sur l’objet interne de type Shape.
+
+<br> 
+
+Maintenant, cela veut dire qu’on peut « écouter » les propriétés `translateX` et `translateY`. 
+
+>**🖥 TODO**
+>
+> - Il ne reste plus qu’à connecter les propriétés correspondantes de l’objet `Text` du décorateur sur ces propriétés (c’est le « *binding* »). Dans le décorateur, lors de l’instanciation de l’objet `Text` : appelez sur l’objet `Text` les méthodes `translateXProperty().bind()` et `translateYProperty().bind()`, en passant en paramètre les appels aux deux méthodes écrites précédemment. 
+> - N’oubliez pas de supprimer l’ancien code qui permettait de déplacer l’objet de type `Text` dans la méthode `offset`. 
+
+Admirez le résultat.🥲
+
+#### 🍹 Amélioration
+En fait, lors du « *binding* », plutôt que de se référer aux `translateX/Y`, il serait plus intéressant d’obtenir directement les coordonnées du centre de la forme, autrement dit la valeur du `translateX` (ou `translateY`) + les coordonnées du centre de la forme au moment de sa création. Ainsi, on n’aurait même plus à initialiser les coordonnés du centre de l’objet `Text` : le *binding* seul suffira.
+
+>**🖥 TODO**
+>
+> - Modifiez les méthodes `translateXProperty()` et `translateYProperty()` pour y ajouter les coordonnées X et Y du centre de la forme. 
+> - Renommez ces méthodes pour que leur nom reflète mieux l'information qu'elles retournent.
+
+<br>
+
+### 🪡 Relier des formes
+---
+Cette fonction très utile va beaucoup simplifier le développement d’une nouvelle fonctionnalité : relier des formes entre elles par un trait. 
+
+>**🖥 TODO**
+>
+> - Commencer par écrire une nouvelle classe `Edge`, qui hérite de `IShape`, et qui possède trois attributs : `from` et `to` de type `IShape`, et `shape` de type `Line`.
+> - La classe aura un constructeur à 2 paramètres de type `IShape`, qui seront les 2 formes à relier. Lors de l’instanciation, le paramètre `shape` sera créé (une nouvelle instance de `Line`). Les coordonnées du point de départ et du point d’arrivée de cette ligne seront liées (avec un « *binding* ») aux propriétés des formes `from` et `to` (grâce aux méthodes écrites précédemment).
+
+NB : Un objet de type `Edge` peut être sélectionné, mais ne peut pas être déplacé. 
+
+>**🖥 TODO**
+>
+> - Créer une *Commande* permettant de relier par un trait les 2 formes sélectionnées (on vérifiera qu’il y a bien 2 formes sélectionnées). Il faudra donc créer une nouvelle instance de `Edge`, et l’ajouter à la liste des `shapes` du `DrawingPane`. 
+
+#### 🏆 Bonus
+En implémentant les méthodes `translateXProperty()` et `translateYProperty()` de la classe `Edge`, de telle sorte qu’elles retournent le *Binding* correspondant aux coordonnées du milieu du segment, alors on peut ajouter du texte sur une ligne, ou même relier des lignes entre elles !
+
+<br>
+
+[🔙 Retour](../README.md)

+ 57 - 0
docs/TP9.md

@@ -0,0 +1,57 @@
+# Minipaint 
+## TP9 – Changement de stratégie
+
+### 🎸 The Edge : la suite
+--- 
+On voudrait pouvoir dessiner plusieurs sortes de traits (droits, courbes, orthogonaux, etc), et être capable de changer dynamiquement le type d’un trait. 
+
+>**🖥 TODO**
+>
+> - Expliquer pourquoi étendre la classe `Edge` avec plusieurs sous-classes (une par type de trait) ne serait pas une bonne solution.
+
+
+
+Dans la classe `Edge`, on va commencer par remplacer le type `Line` (utilisé pour dessiner un trait) par le type `Path`. 
+
+>**🖥 TODO**
+>
+> - Faites les modifications nécessaires. 
+
+Maintenant, pour pouvoir gérer plusieurs sortes de trait, on va utiliser le patron *Strategy*. On aura une stratégie par type de trait. Chaque stratégie sera dédiée à construire un `Path`. Documentez-vous sur ce patron pour comprendre son fonctionnement (une [petite vidéo](https://www.youtube.com/watch?v=v9ejT8FO-7I&t=15s) 📺 ?)
+
+L’interface `IEdgeStrategy` aura une seule méthode :  
+
+	void buildPath(IShape from, IShape to, Path path);
+
+Chaque stratégie implémentera cette méthode en vidant les éléments du path passé en paramètre, et en le remplissant avec les éléments correspondant au calcul du nouveau trait. 
+
+Une stratégie sera passée en paramètre du constructeur de la classe `Edge`, et il sera aussi possible d’en changer grâce à une méthode `setEdgeStrategy(IEdgeStrategy strategy)`. Lorsqu’une nouvelle stratégie sera appliquée à un `Edge`, alors on recalculera par la même occasion le `path` correspondant. 
+
+>**🖥 TODO**
+>
+> - Commencez à implémenter une stratégie simple, qui consistera à simplement tracer un trait droit entre les deux formes. 
+> - Implémentez une deuxième stratégie, permettant de tracer une liaison orthogonale entre 2 formes sélectionnées. 
+> - Créer une commande qui permet d’appliquer une stratégie donnée aux objets de type `Edge` sélectionnés (la stratégie sera passée en paramètre du constructeur de la commande). 
+> - Dans la `ToolBar`, on va rajouter un objet de type `ComboBox` qui contiendra la liste des stratégies possibles. Lorsqu’on va sélectionner une stratégie, elle sera appliquée à tous les objets de type `Edge` qui sont sélectionnés, grâce à l’exécution de la commande correspondante. 
+
+Évidemment, quelques ajustements sont nécessaires pour pouvoir récupérer le « milieu » du trait (grâce aux méthodes `centerXProperty` et `centerYProperty`). En effet, ces informations dépendent du type de trait. 
+
+>**🖥 TODO**
+>
+> - On va donc ajouter deux méthodes à l’interface `IEdgeStrategy` :
+>
+		public ObservableValue middleXProperty();
+		public ObservableValue middleYProperty();
+
+> - On fera appel à ces méthodes dans la classe `Edge`.  
+
+#### 🛵 Un peu plus loin…
+>**🖥 TODO**
+>
+> - Si une seule forme est sélectionnée, alors on doit pouvoir dessiner un lien sur la forme elle-même. 
+
+![](images/minipaint_09.png)
+
+<br>
+
+[🔙 Retour](../README.md)

BIN
docs/images/minipaint_09.png