Subversion Repositories eFlore/Applications.cel

Rev

Rev 155 | Rev 199 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
195 david 1
package org.tela_botanica.client.vues.observation;
155 aurelien 2
import org.tela_botanica.client.interfaces.Rafraichissable;
3
import org.tela_botanica.client.observation.ObservationMediateur;
4
 
5
import com.google.gwt.user.client.Window;
6
import com.gwtext.client.core.EventObject;
7
import com.gwtext.client.data.Node;
8
import com.gwtext.client.data.NodeTraversalCallback;
9
import com.gwtext.client.data.Tree;
10
import com.gwtext.client.widgets.Button;
11
import com.gwtext.client.widgets.Panel;
12
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
13
import com.gwtext.client.widgets.form.TextField;
14
import com.gwtext.client.widgets.layout.VerticalLayout;
15
import com.gwtext.client.widgets.tree.TreeEditor;
16
import com.gwtext.client.widgets.tree.TreeNode;
17
import com.gwtext.client.widgets.tree.TreePanel;
18
import com.gwtext.client.widgets.tree.event.TreeNodeListenerAdapter;
19
import com.gwtext.client.widgets.tree.event.TreePanelListenerAdapter;
20
 
195 david 21
public class ArbreMotsClesObservationVue extends Panel implements Rafraichissable {
155 aurelien 22
 
23
		/**
24
		 * Le médiateur associé à la vue
25
		 */
26
		private ObservationMediateur oMediateur = null;
27
 
28
		/**
29
		 * Le treepanel qui affiche l'arbre
30
		 */
31
		private static TreePanel arbreMotsCles = null;
32
		/**
33
		 * L'éditeur qui permet de modifier les mots clés dans l'arbre
34
		 */
35
		private TreeEditor te = null;
36
		/**
37
		 * Le textfield associé à l'éditeur
38
		 */
39
		private TextField tfEdit = null;
40
		/**
41
		 * Bouton de validation
42
		 */
43
		private Button valider = null;
44
		/**
45
		 * Une string permettant connaitre les mots clés cochés en cours séparés par
46
		 * des virgules
47
		 */
48
		private String motsClesEnCours = "";
49
		/**
50
		 * Tableau contenant les mots clés qui n'ont pas encore été jaouté à l'arbre
51
		 * (sert au lazy rendering quand on reçoit des mots clés avant que le rendu
52
		 * du conteneur n'ai été effectué)
53
		 */
54
		private String[] motsClesEnAttente = new String[0];
55
		/**
56
		 * Booléen d'évènement qui sert à savoir si on est en train d'ajouter un
57
		 * noeud
58
		 */
59
		private boolean ajoutNoeud = false;
60
		/**
61
		 * Booléen d'évènement qui sert à savoir si on est en train de modifier un
62
		 * noeud
63
		 */
64
		private boolean modifNoeud = false;
65
		/**
66
		 * Booléen d'instanciation du conteneur
67
		 */
68
		private boolean arbreCharge = false;
69
		/**
70
		 * Booléen d'évènement qui sert à savoir si les mots clés ont bien été reçu
71
		 */
72
		private boolean motsCleInitialises;
73
 
74
		/**
75
		 * Constructeur sans paramètre (privé car interdit d'utilisation)
76
		 */
77
		@SuppressWarnings("unused")
195 david 78
		private ArbreMotsClesObservationVue() {
155 aurelien 79
			super();
80
		}
81
 
82
		/**
83
		 * Constructeur avec paramètre
84
		 *
85
		 * @param im
86
		 *            le médiateur à associer
87
		 */
195 david 88
		public ArbreMotsClesObservationVue(ObservationMediateur om) {
155 aurelien 89
			// on crée le panel
90
			super("Mots clés");
91
			this.setLayout(new VerticalLayout());
92
			oMediateur = om;
93
 
94
			// on crée le conteneur de l'arbre
95
			arbreMotsCles = new TreePanel();
96
			// on permet le drag and drop dans l'arbre
97
			arbreMotsCles.setEnableDD(true);
98
			arbreMotsCles.setId("x-view-tree-keyword-obs");
99
 
100
			// on crée une racine pour l'arbre
101
			TreeNode root = new TreeNode("Tags");
102
			root.setId("racine_obs");
103
			String[] usObject = { "Mots clés", "racine" };
104
			root.setUserObject(usObject);
105
			root.setExpandable(true);
106
			arbreMotsCles.setRootNode(root);
107
			arbreMotsCles.setRootVisible(true);
108
			arbreMotsCles.setBorder(false);
109
			arbreMotsCles.setWidth(500);
110
 
111
			arbreMotsCles.getRootNode().addListener(new TreeNodeListenerAdapter() {
112
				public void onClick(Node node, EventObject e) {
113
					if(!arbreCharge) {
114
						expand();
115
					}
116
				}
117
 
118
				public void onExpand(Node node) {
119
					if(!arbreCharge) {
120
						obtenirArbreMotsCles();
121
						arbreCharge = true;
122
					}
123
				}
124
			});
125
 
126
			// on crée l'éditeur pour l'arbre
127
			tfEdit = new TextField();
128
			tfEdit.setAutoWidth(true);
129
			te = new TreeEditor(arbreMotsCles, tfEdit);
130
			valider = new Button("Appliquer");
131
			arbreMotsCles.add(te);
132
 
133
			// on met en forme le layout
134
			this.add(arbreMotsCles);
135
			this.add(valider);
136
 
137
			this.setBorder(false);
138
			this.setCollapsible(true);
139
			this.setTitleCollapse(true);
140
 
141
			// on ajoute les listeners
142
			ajouterListeners();
143
 
144
		}
145
 
146
		/**
147
		 * Acesseur pour le médiateur
148
		 *
149
		 * @return le médiateur associé à la vue
150
		 */
151
		private ObservationMediateur getOMediateur() {
152
 
153
			return oMediateur;
154
 
155
		}
156
 
157
		/**
158
		 * Acesseur pour l'arbre des mots clés
159
		 *
160
		 * @return le panel contenant l'arbre
161
		 */
162
		public TreePanel getArbreMotsCles() {
163
			return arbreMotsCles;
164
		}
165
 
166
		/**
167
		 * Accesseur pour l'éditeur
168
		 *
169
		 * @return l'éditeur associé à l'arbre
170
		 */
171
		public TreeEditor getTe() {
172
			return te;
173
		}
174
 
175
		/**
176
		 * Acesseur pour le TextField associé à l'éditeur
177
		 *
178
		 * @return le champ texte associé à l'éditeur
179
		 */
180
		public TextField getTfEdit() {
181
			return tfEdit;
182
		}
183
 
184
		/**
185
		 * Ajoute les listeners nécessaires pour la gestion des évènements
186
		 */
187
		private void ajouterListeners() {
188
			arbreMotsCles.addListener(new TreePanelListenerAdapter() {
189
 
190
				// gestion du clic sur un noeud
191
				public void onClick(TreeNode node, EventObject e) {
192
 
193
					e.stopEvent();
194
					gererClicNoeud(node);
195
				}
196
 
197
				// gestion du clic droit sur un noeud
198
				public void onContextMenu(TreeNode node, EventObject e) {
199
 
200
					e.stopEvent();
201
					getOMediateur().montrerContextMenuArbre(node, e, getTe());
202
 
203
				}
204
 
205
				// gestion du double clic sur un noeud
206
				public void onDblClick(TreeNode node, EventObject e) {
207
 
208
					modifNoeud = true;
209
					if (!node.getId().equals("racine_obs")) {
210
						te.startEdit(node);
211
					}
212
				}
213
 
214
				// gestion de la modification du texte d'un noeud
215
				public void onTextChange(TreeNode node, String text, String oldText) {
216
 
217
					// on récupère les informations associées au noeud
218
					TreeNode nd = node;
219
					String[] usObject = new String[2];
220
					usObject[0] = text;
221
					usObject[1] = ((String[]) nd.getUserObject())[1];
222
					nd.setUserObject(usObject);
223
 
224
					// si c'est un nouveau noeud
225
					if (ajoutNoeud) {
226
						// on notifie le médiateur de l'ajout et on lui passe
227
						// l'arbre
228
						getOMediateur().ajouterMotCleDansArbre(nd,
229
								getArbreMotsCles().getTree());
230
						// et considère l'ajout achevé
231
						ajoutNoeud = false;
232
					}
233
					// si c'est noeud déjà existant
234
					else {
235
						if (modifNoeud) {
236
							// on notifie le médiateur de la modification et on lui
237
							// passe l'arbre
238
							getOMediateur().modifierMotCleDansArbre(nd,
239
									getArbreMotsCles().getTree());
240
							// et on considère la modification achevée
241
							modifNoeud = false;
242
						}
243
					}
244
 
245
				}
246
 
247
				// gestion du déplacement d'un noeud
248
				public void onMoveNode(Tree tree, TreeNode node,
249
						TreeNode oldParent, TreeNode newParent, int index) {
250
					// on notifie le médiateur et on lui passe l'arbre
251
					getOMediateur().deplacerMotCleDansArbre(node,
252
							getArbreMotsCles().getTree());
253
				}
254
 
255
			});
256
 
257
			// gestion de la validation
258
			valider.addListener(new ButtonListenerAdapter() {
259
 
260
				// lors du clic
261
				public void onClick(Button button, EventObject e) {
262
 
263
					// on vide les mots clés en cours
264
					motsClesEnCours = "";
265
					// pour chaque noeud à partir de la racine
266
					getArbreMotsCles().getRootNode().cascade(
267
							new NodeTraversalCallback() {
268
 
269
								// on éxécute une fonction
270
								public boolean execute(Node node) {
271
 
272
									// on récupère le mot clé associé au noeud et
273
									// ses infos
274
									TreeNode tn = getArbreMotsCles().getNodeById(
275
											node.getId());
276
 
277
									String[] usObject = (String[]) tn
278
											.getUserObject();
279
									getOMediateur().mettreAjourMotsClesId(
280
											usObject[0], usObject[1]);
281
 
282
									if (tn.getUI().isChecked()) {
283
										// et les concatène à la string des mots
284
										// clés en cours
285
										motsClesEnCours += usObject[1] + ",";
286
									}
287
 
288
									return true;
289
								}
290
 
291
							});
292
 
293
					// enfin on notifie le médiateur et on lui passe l'arbre et la
294
					// liste des mots clés ainsi obtenue
295
					getOMediateur().mettreAjourMotsCles(motsClesEnCours,
296
							arbreMotsCles.getTree());
297
				}
298
			});
299
 
300
		}
301
 
302
		/**
303
		 * Envoie une demande au médiateur pour obtenir l'arbre des mots clés
304
		 */
305
		public void obtenirArbreMotsCles() {
306
 
307
			getOMediateur().obtenirArbreMotsCles(this);
308
 
309
		}
310
 
311
		/**
312
		 * Supprime un noeud de l'arbre
313
		 *
314
		 * @param n
315
		 *            le noeud à supprimer
316
		 */
317
		public void supprimerNoeud(TreeNode n) {
318
			// si ça n'est pas la racine (qu'on ne peut pas supprimer)
319
			if (!n.getId().equals(getArbreMotsCles().getRootNode().getId())) {
320
				// on détache le noeud et on le détruit
321
				n.getParentNode().removeChild(n);
322
				n.destroy();
323
				// puis on en notifie le médiateur en lui passant le noeud supprimé
324
				// et l'arbre
325
				getOMediateur()
326
						.supprimerMotCleDansArbre(n, arbreMotsCles.getTree());
327
			} else {
328
				// si l'utilisateur tente de supprimer la racine, on l'avertit de
329
				// son erreur
330
				Window.alert("Impossible de supprimer la racine de l'arbre");
331
			}
332
		}
333
 
334
		/**
335
		 * Ajoute un noeud dans l'arbre au parent donné
336
		 *
337
		 * @param parent
338
		 *            le futur parent du noeud à ajouter
339
		 */
340
		public void ajouterNoeud(TreeNode parent) {
341
 
342
			// on met l'ajout du noeud à vrai
343
			ajoutNoeud = true;
344
			// on crée un nouveau noeud vide
345
			TreeNode nd = new TreeNode("");
346
			nd.setCls("x-view-treenode-keyword");
347
			nd.setChecked(true);
348
			// on associe un objet au noeud qui contient des infos
349
			String[] usObject = new String[2];
350
			// l'objet contient le nom du noeud
351
			usObject[0] = "";
352
			usObject[1] = genererIdMotCle(nd);
353
			nd.setId(usObject[1]);
354
			nd.setUserObject(usObject);
355
			// l'identifiant d'un noeud c'est son hashcode
356
			// l'objet associé au noeud contient aussi son identifiant
357
 
358
			// on le concatène au parent et on étend ses enfants
359
			parent.appendChild(nd);
360
			parent.expand();
361
			// enfin on place le curseur et on fait apparaitre le champ d'édition
362
			// pour que l'utilisateur nomme son mot clé
363
			te.startEdit(nd);
364
 
365
		}
366
 
367
		/**
368
		 * Coche le noeud s'il est décoché, le décoche sinon
369
		 *
370
		 * @param node
371
		 */
372
		public void gererClicNoeud(TreeNode node) {
373
			if (node.getUI().isChecked()) {
374
				node.getUI().toggleCheck(false);
375
			} else {
376
				node.getUI().toggleCheck(true);
377
			}
378
		}
379
 
380
		/**
381
		 * Parcourt l'arbre et coche les noeud qui font partie de la liste des mots
382
		 * clés à cocher
383
		 *
384
		 * @param motsClesIds
385
		 *            un tableau contenant les identifiants des mots clés à cocher
386
		 */
387
		public void cocherMotsCles(final String[] motsClesIds) {
388
			if (getArbreMotsCles() != null
389
					&& getArbreMotsCles().getRootNode() != null) {
390
				// à partir de la racine
391
				getArbreMotsCles().getRootNode().cascade(
392
						new NodeTraversalCallback() {
393
 
394
							// pour chaque noeud
395
							public boolean execute(Node node) {
396
 
397
								getArbreMotsCles().getNodeById(node.getId())
398
								.getUI().toggleCheck(false);
399
 
400
								// on parcourt le tableau des mots clés
401
								for (int i = 0; i < motsClesIds.length; i++) {
402
									// si le mot clé fait partie des id à cocher on
403
									// le coche
404
									String usObject[] = (String[]) node
405
											.getUserObject();
406
									String nodeId = usObject[1];
407
 
408
									if (nodeId.equals(motsClesIds[i])) {
409
											getArbreMotsCles().getNodeById(nodeId+"_obs")
410
													.getUI().toggleCheck(true);
411
 
412
											return true;
413
									}
414
								}
415
								// et on passe au suivant
416
								return true;
417
							}
418
 
419
						});
420
			}
421
			else {
422
				motsClesEnAttente = motsClesIds ;
423
			}
424
		}
425
 
426
		/**
427
		 * Méthode héritée de l'interface rafraichissable
428
		 *
429
		 * @param nouvelleDonnees
430
		 *            les nouvelles données pour l'objet
431
		 * @param repandreRafraichissement
432
		 *            booleen qui dit si on doit répandre l'évenement
433
		 */
434
		public void rafraichir(Object nouvelleDonnees,
435
				boolean repandreRafraichissement) {
436
 
437
			if(nouvelleDonnees instanceof Tree) {
438
 
439
				Tree nouvelArbre = (Tree)nouvelleDonnees ;
440
 
441
				// on prend sa racine et on l'attache à l'arbre des mots clés
442
				Node[] rootChild = getArbreMotsCles().getRootNode().getChildNodes();
443
				for (int i = 0; i < rootChild.length; i++) {
444
 
445
					rootChild[i].remove();
446
				}
447
 
448
				copierFilsNoeud(nouvelArbre.getRootNode(),getArbreMotsCles().getRootNode());
449
 
450
				// si l'arbre n'était pas encore considéré comme instancié
451
				if (!arbreCharge) {
452
					// on signale que oui
453
					arbreCharge = true;
454
				}
455
 
456
				// s'il y a des mots clés en attente (lors du premier rendering)
457
				if (motsCleInitialises == false && motsClesEnAttente != null) {
458
					// on les coche
459
					// cocherMotsCles(motsClesEnAttente) ;
460
					motsCleInitialises = true;
461
				}
462
 
463
				if(motsClesEnAttente.length > 0) {
464
							cocherMotsCles(motsClesEnAttente);
465
				}
466
			}
467
 
468
			// Si on reçoit un tableau de String (cas ou l'on séléectionne une
469
			// nouvelle image)
470
			if (nouvelleDonnees instanceof String[]) {
471
				// et que l'arbre est instancié
472
				if (arbreCharge) {
473
					// le tableau de String contient les id des mots clés associés à
474
					// l'image
475
					// on coche les mots clés contenu dans le tableau
476
					String[] motsClesIds = (String[]) nouvelleDonnees;
477
					cocherMotsCles(motsClesIds);
478
 
479
				}
480
				// si l'arbre n'est pas encore instancié on met les mots clés en
481
				// attente
482
				else {
483
					motsClesEnAttente = (String[]) nouvelleDonnees;
484
				}
485
			}
486
		}
487
 
488
		private String genererIdMotCle(TreeNode nd) {
489
			return "" + (nd.hashCode() + (Math.random() * 10000));
490
		}
491
 
492
		/**
493
		 * Fonction récursive qui prend deux noeuds d'arbre en paramètre et crée un
494
		 * copie du sous arbre du premier noeud, qu'elle concatène au deuxième
495
		 *
496
		 * @param ndPereOriginal
497
		 *            le père des noeuds de l'arbre original
498
		 * @param ndPereCopie
499
		 *            le père qui va recevoir les copies
500
		 */
501
		private void copierFilsNoeud(Node ndPereOriginal, TreeNode ndPereCopie) {
502
			if (ndPereCopie != null && ndPereOriginal != null) {
503
				Node[] ndNodeFils = ndPereOriginal.getChildNodes();
504
 
505
				for (int i = 0; i < ndNodeFils.length; i++) {
506
 
507
					String[] usObj = (String[]) ndNodeFils[i].getUserObject();
508
					TreeNode child = new TreeNode(usObj[0]);
509
					child.setId(usObj[1] +"_obs");
510
					child.setChecked(false);
511
					child.setUserObject(usObj);
512
					ndPereCopie.appendChild(child);
513
 
514
					if (!ndNodeFils[i].isLeaf()) {
515
						copierFilsNoeud(ndNodeFils[i], child);
516
					}
517
 
518
				}
519
			}
520
		}
521
}