Subversion Repositories eFlore/Applications.cel

Rev

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

Rev Author Line No. Line
199 david 1
package org.tela_botanica.client.vues.observation.filtres;
318 aurelien 2
import org.tela_botanica.client.interfaces.Filtrable;
155 aurelien 3
import org.tela_botanica.client.interfaces.Rafraichissable;
4
import org.tela_botanica.client.observation.ObservationMediateur;
318 aurelien 5
import org.tela_botanica.client.vues.observation.ListeObservationVue;
155 aurelien 6
 
335 aurelien 7
import com.google.gwt.core.client.GWT;
318 aurelien 8
import com.google.gwt.core.client.JavaScriptObject;
155 aurelien 9
import com.google.gwt.user.client.Window;
318 aurelien 10
import com.google.gwt.user.client.ui.KeyboardListener;
155 aurelien 11
import com.gwtext.client.core.EventObject;
12
import com.gwtext.client.data.Node;
13
import com.gwtext.client.data.NodeTraversalCallback;
318 aurelien 14
import com.gwtext.client.data.Record;
155 aurelien 15
import com.gwtext.client.data.Tree;
318 aurelien 16
import com.gwtext.client.dd.DD;
17
import com.gwtext.client.dd.DragData;
18
import com.gwtext.client.dd.DragDrop;
19
import com.gwtext.client.dd.DragSource;
20
import com.gwtext.client.dd.DropTarget;
21
import com.gwtext.client.dd.DropTargetConfig;
22
import com.gwtext.client.widgets.BoxComponent;
155 aurelien 23
import com.gwtext.client.widgets.Button;
318 aurelien 24
import com.gwtext.client.widgets.Component;
25
import com.gwtext.client.widgets.Container;
155 aurelien 26
import com.gwtext.client.widgets.Panel;
27
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
318 aurelien 28
import com.gwtext.client.widgets.event.PanelListenerAdapter;
155 aurelien 29
import com.gwtext.client.widgets.form.TextField;
318 aurelien 30
import com.gwtext.client.widgets.grid.GridDragData;
31
import com.gwtext.client.widgets.grid.GridView;
155 aurelien 32
import com.gwtext.client.widgets.layout.VerticalLayout;
318 aurelien 33
import com.gwtext.client.widgets.tree.DropNodeCallback;
34
import com.gwtext.client.widgets.tree.MultiSelectionModel;
35
import com.gwtext.client.widgets.tree.TreeDragData;
36
import com.gwtext.client.widgets.tree.TreeDropZone;
37
import com.gwtext.client.widgets.tree.TreeDropZoneConfig;
155 aurelien 38
import com.gwtext.client.widgets.tree.TreeEditor;
39
import com.gwtext.client.widgets.tree.TreeNode;
40
import com.gwtext.client.widgets.tree.TreePanel;
41
import com.gwtext.client.widgets.tree.event.TreeNodeListenerAdapter;
318 aurelien 42
import com.gwtext.client.widgets.tree.event.TreePanelListener;
155 aurelien 43
import com.gwtext.client.widgets.tree.event.TreePanelListenerAdapter;
44
 
318 aurelien 45
public class ArbreMotsClesObservationVue extends Panel implements Rafraichissable, Filtrable {
155 aurelien 46
 
47
		/**
48
		 * Le médiateur associé à la vue
49
		 */
50
		private ObservationMediateur oMediateur = null;
51
 
52
		/**
53
		 * Le treepanel qui affiche l'arbre
54
		 */
55
		private static TreePanel arbreMotsCles = null;
56
		/**
57
		 * L'éditeur qui permet de modifier les mots clés dans l'arbre
58
		 */
59
		private TreeEditor te = null;
60
		/**
61
		 * Le textfield associé à l'éditeur
62
		 */
63
		private TextField tfEdit = null;
64
		/**
65
		 * Bouton de validation
66
		 */
318 aurelien 67
		private Button ajouterMotCle = null;
155 aurelien 68
		/**
69
		 * Une string permettant connaitre les mots clés cochés en cours séparés par
70
		 * des virgules
71
		 */
72
		private String motsClesEnCours = "";
73
		/**
74
		 * Tableau contenant les mots clés qui n'ont pas encore été jaouté à l'arbre
75
		 * (sert au lazy rendering quand on reçoit des mots clés avant que le rendu
76
		 * du conteneur n'ai été effectué)
77
		 */
78
		private String[] motsClesEnAttente = new String[0];
79
		/**
80
		 * Booléen d'évènement qui sert à savoir si on est en train d'ajouter un
81
		 * noeud
82
		 */
83
		private boolean ajoutNoeud = false;
84
		/**
85
		 * Booléen d'évènement qui sert à savoir si on est en train de modifier un
86
		 * noeud
87
		 */
88
		private boolean modifNoeud = false;
89
		/**
90
		 * Booléen d'instanciation du conteneur
91
		 */
92
		private boolean arbreCharge = false;
318 aurelien 93
 
155 aurelien 94
		/**
318 aurelien 95
		 * Booléen nécessaire pour l'affichage
96
		 *
97
		 */
98
		private boolean estInstancie = false;
99
 
100
		/**
155 aurelien 101
		 * Booléen d'évènement qui sert à savoir si les mots clés ont bien été reçu
102
		 */
103
		private boolean motsCleInitialises;
318 aurelien 104
 
105
		private Component livue = null;
335 aurelien 106
 
107
		MultiSelectionModel msModel = null;
155 aurelien 108
 
109
		/**
110
		 * Constructeur sans paramètre (privé car interdit d'utilisation)
111
		 */
112
		@SuppressWarnings("unused")
195 david 113
		private ArbreMotsClesObservationVue() {
155 aurelien 114
			super();
115
		}
116
 
117
		/**
118
		 * Constructeur avec paramètre
119
		 *
120
		 * @param im
121
		 *            le médiateur à associer
122
		 */
195 david 123
		public ArbreMotsClesObservationVue(ObservationMediateur om) {
155 aurelien 124
			// on crée le panel
125
			super("Mots clés");
318 aurelien 126
 
155 aurelien 127
			this.setLayout(new VerticalLayout());
128
			oMediateur = om;
318 aurelien 129
 
130
			setBorder(false);
131
			setCollapsible(true);
132
			setTitleCollapse(true);
155 aurelien 133
 
318 aurelien 134
			// on ajoute les listeners
135
			ajouterListenersPanel();
155 aurelien 136
 
318 aurelien 137
		}
138
 
139
		/**
140
		 * Ajoute les listeners pour le rendu du panel
141
		 */
142
		private void ajouterListenersPanel() {
143
			  this.addListener(new PanelListenerAdapter() {
155 aurelien 144
 
318 aurelien 145
				// on instancie réellement les composants au moment du rendu pour
146
				// accélérer l'affichage
147
				// et éviter des bugs
148
				public void onRender(Component component) {
149
 
150
					livue = oMediateur.getListeObservation();
151
 
152
					// on crée le conteneur de l'arbre
153
					arbreMotsCles = new TreePanel();
154
					// on permet le drag and drop dans l'arbre
155
					//arbreMotsCles.setEnableDD(true);
156
					arbreMotsCles.setId("x-view-tree-keyword-obs");
157
 
158
 
335 aurelien 159
					msModel = new MultiSelectionModel();
318 aurelien 160
					arbreMotsCles.setSelectionModel(msModel);
155 aurelien 161
 
318 aurelien 162
					// on crée une racine pour l'arbre
163
					TreeNode root = new TreeNode("Tags");
164
					root.setId("racine_obs");
165
					String[] usObject = { "Mots clés", "racine_obs" };
166
					root.setUserObject(usObject);
167
					root.setExpandable(true);
168
 
169
					arbreMotsCles.setRootNode(root);
170
 
171
					// on crée l'éditeur pour l'arbre
172
					tfEdit = new TextField();
173
					te = new TreeEditor(arbreMotsCles, tfEdit);
174
					ajouterMotCle = new Button("Nouveau mot clé");
175
					arbreMotsCles.add(te);
176
 
177
					arbreMotsCles.getRootNode().addListener(new TreeNodeListenerAdapter() {
178
						public void onClick(Node node, EventObject e) {
179
							if(!arbreCharge) {
180
								expand();
181
							}
182
						}
155 aurelien 183
 
318 aurelien 184
						public void onExpand(Node node) {
185
							if(!arbreCharge) {
186
								obtenirArbreMotsCles();
187
								arbreCharge = true;
188
							}
189
						}
190
					});
155 aurelien 191
 
318 aurelien 192
					// on interdit le drag and drop dans l'arbre
193
					arbreMotsCles.setRootVisible(true);
194
					arbreMotsCles.setBorder(false);
195
 
196
					// on met en forme le layout
197
					add(arbreMotsCles);
198
					add(ajouterMotCle);
155 aurelien 199
 
318 aurelien 200
					// enfin on considère le composant comme instancié
201
					estInstancie = true;
202
 
203
					configDragAndDrop();
204
 
205
					// on ajoute les listeners d'évenements
206
					ajouterListeners();
207
				}
208
 
209
			});
155 aurelien 210
		}
211
 
212
		/**
213
		 * Acesseur pour le médiateur
214
		 *
215
		 * @return le médiateur associé à la vue
216
		 */
217
		private ObservationMediateur getOMediateur() {
218
 
219
			return oMediateur;
220
 
221
		}
222
 
223
		/**
224
		 * Acesseur pour l'arbre des mots clés
225
		 *
226
		 * @return le panel contenant l'arbre
227
		 */
228
		public TreePanel getArbreMotsCles() {
229
			return arbreMotsCles;
230
		}
231
 
232
		/**
233
		 * Accesseur pour l'éditeur
234
		 *
235
		 * @return l'éditeur associé à l'arbre
236
		 */
237
		public TreeEditor getTe() {
238
			return te;
239
		}
240
 
241
		/**
242
		 * Acesseur pour le TextField associé à l'éditeur
243
		 *
244
		 * @return le champ texte associé à l'éditeur
245
		 */
246
		public TextField getTfEdit() {
247
			return tfEdit;
248
		}
249
 
250
		/**
251
		 * Ajoute les listeners nécessaires pour la gestion des évènements
252
		 */
253
		private void ajouterListeners() {
254
			arbreMotsCles.addListener(new TreePanelListenerAdapter() {
255
 
256
				// gestion du clic sur un noeud
257
				public void onClick(TreeNode node, EventObject e) {
258
 
259
					e.stopEvent();
318 aurelien 260
					boolean multi = false;
261
					if(e.hasModifier()) {
262
						multi = true;
263
					}
264
					gererClicNoeud(node,multi);
155 aurelien 265
				}
266
 
267
				// gestion du clic droit sur un noeud
268
				public void onContextMenu(TreeNode node, EventObject e) {
269
 
270
					e.stopEvent();
271
					getOMediateur().montrerContextMenuArbre(node, e, getTe());
272
 
273
				}
274
 
275
				// gestion du double clic sur un noeud
276
				public void onDblClick(TreeNode node, EventObject e) {
277
 
278
					modifNoeud = true;
279
					if (!node.getId().equals("racine_obs")) {
280
						te.startEdit(node);
281
					}
282
				}
283
 
284
				// gestion de la modification du texte d'un noeud
285
				public void onTextChange(TreeNode node, String text, String oldText) {
286
 
287
					// on récupère les informations associées au noeud
288
					TreeNode nd = node;
289
					String[] usObject = new String[2];
290
					usObject[0] = text;
291
					usObject[1] = ((String[]) nd.getUserObject())[1];
292
					nd.setUserObject(usObject);
293
 
294
					// si c'est un nouveau noeud
295
					if (ajoutNoeud) {
296
						// on notifie le médiateur de l'ajout et on lui passe
297
						// l'arbre
298
						getOMediateur().ajouterMotCleDansArbre(nd,
299
								getArbreMotsCles().getTree());
300
						// et considère l'ajout achevé
301
						ajoutNoeud = false;
302
					}
303
					// si c'est noeud déjà existant
304
					else {
305
						if (modifNoeud) {
306
							// on notifie le médiateur de la modification et on lui
307
							// passe l'arbre
308
							getOMediateur().modifierMotCleDansArbre(nd,
309
									getArbreMotsCles().getTree());
310
							// et on considère la modification achevée
311
							modifNoeud = false;
312
						}
313
					}
314
 
315
				}
316
 
317
				// gestion du déplacement d'un noeud
318
				public void onMoveNode(Tree tree, TreeNode node,
319
						TreeNode oldParent, TreeNode newParent, int index) {
320
					// on notifie le médiateur et on lui passe l'arbre
321
					getOMediateur().deplacerMotCleDansArbre(node,
322
							getArbreMotsCles().getTree());
323
				}
318 aurelien 324
 
325
				public boolean doBeforeNodeDrop(TreePanel treePanel,
326
						TreeNode target, DragData dragData,
327
						String point, DragDrop source,
328
						TreeNode dropNode,
329
						DropNodeCallback dropNodeCallback) {
330
 
331
					if(dragData instanceof GridDragData) {
332
 
333
						Record[] obsALier = ((GridDragData)dragData).getSelections();
334
 
335
						String idObsALier[] = new String[obsALier.length];
336
						String idMotCle = ((String[])target.getUserObject())[1];
337
						String idObsALierString = "";
338
 
339
						for(int i = 0; i < obsALier.length; i++) {
340
							idObsALierString += obsALier[i].getAsString("ordre_observation")+", ";
341
							idObsALier[i] = obsALier[i].getAsString("ordre_observation");
342
						}
343
 
335 aurelien 344
						if(Window.confirm("lier les observations "+idObsALierString+" au mot clé "+target.getText()+" ?")) {
318 aurelien 345
							oMediateur.mettreAjourMotsCles(idMotCle, idObsALier);
346
						}
347
					}
348
					return true;
349
				}
155 aurelien 350
 
318 aurelien 351
 
352
				public void onNodeDrop(TreePanel treePanel,
353
						TreeNode target, DragData dragData,
354
						String point, DragDrop source, TreeNode dropNode) {
355
 
356
				}
357
 
155 aurelien 358
			});
359
 
360
			// gestion de la validation
318 aurelien 361
			ajouterMotCle.addListener(new ButtonListenerAdapter() {
155 aurelien 362
 
363
				// lors du clic
364
				public void onClick(Button button, EventObject e) {
318 aurelien 365
 
366
					ajouterNoeud(arbreMotsCles.getRootNode());
367
 
155 aurelien 368
				}
369
			});
370
 
371
		}
318 aurelien 372
 
373
 
374
		/**
375
		 * Configure le drag 'n drop pour la liste
376
		 */
377
		private void configDragAndDrop()
378
		{
155 aurelien 379
 
318 aurelien 380
			// on fabrique la nouvelle configuration
381
			// les éléments sur lesquels on fait du drag 'n drop doivent tous avoir le même ddGroup
382
			arbreMotsCles.setDdGroup("ObsMotsClesGroup");
383
			//arbreMotsCles.setEnableDD(true);
384
			arbreMotsCles.setEnableDrag(true);
385
			arbreMotsCles.setEnableDrop(true);
386
			DropTargetConfig dtc = new DropTargetConfig();
387
			dtc.setdDdGroup("ObsMotsClesGroup");
388
 
389
	         DropTarget tg = new DropTarget(livue, dtc) {
390
	             public boolean notifyDrop(DragSource source, EventObject e,
391
	                   DragData data) {
392
 
393
	                 return true;
394
	             }
395
 
396
	             public String notifyOver(DragSource source, EventObject e,
397
	                   DragData data) {
398
	                return "x-dd-drop-ok";
399
	             }
400
	         };
401
		}
402
 
155 aurelien 403
		/**
404
		 * Envoie une demande au médiateur pour obtenir l'arbre des mots clés
405
		 */
406
		public void obtenirArbreMotsCles() {
407
 
408
			getOMediateur().obtenirArbreMotsCles(this);
409
 
410
		}
411
 
412
		/**
413
		 * Supprime un noeud de l'arbre
414
		 *
415
		 * @param n
416
		 *            le noeud à supprimer
417
		 */
418
		public void supprimerNoeud(TreeNode n) {
419
			// si ça n'est pas la racine (qu'on ne peut pas supprimer)
420
			if (!n.getId().equals(getArbreMotsCles().getRootNode().getId())) {
421
				// on détache le noeud et on le détruit
422
				n.getParentNode().removeChild(n);
423
				n.destroy();
424
				// puis on en notifie le médiateur en lui passant le noeud supprimé
425
				// et l'arbre
426
				getOMediateur()
427
						.supprimerMotCleDansArbre(n, arbreMotsCles.getTree());
428
			} else {
429
				// si l'utilisateur tente de supprimer la racine, on l'avertit de
430
				// son erreur
431
				Window.alert("Impossible de supprimer la racine de l'arbre");
432
			}
433
		}
434
 
435
		/**
436
		 * Ajoute un noeud dans l'arbre au parent donné
437
		 *
438
		 * @param parent
439
		 *            le futur parent du noeud à ajouter
440
		 */
441
		public void ajouterNoeud(TreeNode parent) {
442
 
443
			// on met l'ajout du noeud à vrai
444
			ajoutNoeud = true;
445
			// on crée un nouveau noeud vide
446
			TreeNode nd = new TreeNode("");
447
			nd.setCls("x-view-treenode-keyword");
448
			// on associe un objet au noeud qui contient des infos
449
			String[] usObject = new String[2];
450
			// l'objet contient le nom du noeud
451
			usObject[0] = "";
452
			usObject[1] = genererIdMotCle(nd);
453
			nd.setId(usObject[1]);
454
			nd.setUserObject(usObject);
455
			// l'identifiant d'un noeud c'est son hashcode
456
			// l'objet associé au noeud contient aussi son identifiant
457
 
458
			// on le concatène au parent et on étend ses enfants
459
			parent.appendChild(nd);
460
			parent.expand();
461
			// enfin on place le curseur et on fait apparaitre le champ d'édition
462
			// pour que l'utilisateur nomme son mot clé
463
			te.startEdit(nd);
464
 
465
		}
466
 
467
		/**
318 aurelien 468
		 * Fonction de gestion sur le clic sur le noeud
155 aurelien 469
		 *
470
		 * @param node
471
		 */
318 aurelien 472
		public void gererClicNoeud(TreeNode node, boolean multi) {
473
 
335 aurelien 474
			//((MultiSelectionModel)arbreMotsCles.getSelectionModel()).select(node, multi);
475
			motsClesEnCours = node.getId();
476
			oMediateur.obtenirNombreObservation();
155 aurelien 477
		}
478
 
479
		/**
480
		 * Parcourt l'arbre et coche les noeud qui font partie de la liste des mots
481
		 * clés à cocher
482
		 *
483
		 * @param motsClesIds
484
		 *            un tableau contenant les identifiants des mots clés à cocher
485
		 */
486
		public void cocherMotsCles(final String[] motsClesIds) {
487
			if (getArbreMotsCles() != null
488
					&& getArbreMotsCles().getRootNode() != null) {
489
				// à partir de la racine
490
				getArbreMotsCles().getRootNode().cascade(
491
						new NodeTraversalCallback() {
492
 
493
							// pour chaque noeud
494
							public boolean execute(Node node) {
495
 
318 aurelien 496
								//getArbreMotsCles().getNodeById(node.getId())
497
								//.getUI().toggleCheck(false);
155 aurelien 498
 
499
								// on parcourt le tableau des mots clés
500
								for (int i = 0; i < motsClesIds.length; i++) {
501
									// si le mot clé fait partie des id à cocher on
502
									// le coche
503
									String usObject[] = (String[]) node
504
											.getUserObject();
505
									String nodeId = usObject[1];
506
 
507
									if (nodeId.equals(motsClesIds[i])) {
318 aurelien 508
											//getArbreMotsCles().getNodeById(nodeId+"_obs")
509
											//		.getUI().toggleCheck(true);
155 aurelien 510
 
511
											return true;
512
									}
513
								}
514
								// et on passe au suivant
515
								return true;
516
							}
517
 
518
						});
519
			}
520
			else {
521
				motsClesEnAttente = motsClesIds ;
522
			}
523
		}
524
 
525
		/**
526
		 * Méthode héritée de l'interface rafraichissable
527
		 *
528
		 * @param nouvelleDonnees
529
		 *            les nouvelles données pour l'objet
530
		 * @param repandreRafraichissement
531
		 *            booleen qui dit si on doit répandre l'évenement
532
		 */
533
		public void rafraichir(Object nouvelleDonnees,
534
				boolean repandreRafraichissement) {
535
 
536
			if(nouvelleDonnees instanceof Tree) {
537
 
538
				Tree nouvelArbre = (Tree)nouvelleDonnees ;
539
 
540
				// on prend sa racine et on l'attache à l'arbre des mots clés
541
				Node[] rootChild = getArbreMotsCles().getRootNode().getChildNodes();
542
				for (int i = 0; i < rootChild.length; i++) {
543
 
544
					rootChild[i].remove();
545
				}
546
 
547
				copierFilsNoeud(nouvelArbre.getRootNode(),getArbreMotsCles().getRootNode());
548
 
549
				// si l'arbre n'était pas encore considéré comme instancié
550
				if (!arbreCharge) {
551
					// on signale que oui
552
					arbreCharge = true;
553
				}
554
 
318 aurelien 555
				/*
155 aurelien 556
				// s'il y a des mots clés en attente (lors du premier rendering)
557
				if (motsCleInitialises == false && motsClesEnAttente != null) {
558
					// on les coche
559
					// cocherMotsCles(motsClesEnAttente) ;
560
					motsCleInitialises = true;
561
				}
562
 
563
				if(motsClesEnAttente.length > 0) {
564
							cocherMotsCles(motsClesEnAttente);
318 aurelien 565
				}*/
155 aurelien 566
			}
567
 
568
			// Si on reçoit un tableau de String (cas ou l'on séléectionne une
318 aurelien 569
			// nouvelle obs)
155 aurelien 570
			if (nouvelleDonnees instanceof String[]) {
571
				// et que l'arbre est instancié
572
				if (arbreCharge) {
573
					// le tableau de String contient les id des mots clés associés à
574
					// l'image
575
					// on coche les mots clés contenu dans le tableau
576
					String[] motsClesIds = (String[]) nouvelleDonnees;
577
					cocherMotsCles(motsClesIds);
578
 
579
				}
580
				// si l'arbre n'est pas encore instancié on met les mots clés en
581
				// attente
582
				else {
583
					motsClesEnAttente = (String[]) nouvelleDonnees;
584
				}
585
			}
586
		}
587
 
588
		private String genererIdMotCle(TreeNode nd) {
589
			return "" + (nd.hashCode() + (Math.random() * 10000));
590
		}
591
 
592
		/**
593
		 * Fonction récursive qui prend deux noeuds d'arbre en paramètre et crée un
594
		 * copie du sous arbre du premier noeud, qu'elle concatène au deuxième
595
		 *
596
		 * @param ndPereOriginal
597
		 *            le père des noeuds de l'arbre original
598
		 * @param ndPereCopie
599
		 *            le père qui va recevoir les copies
600
		 */
601
		private void copierFilsNoeud(Node ndPereOriginal, TreeNode ndPereCopie) {
602
			if (ndPereCopie != null && ndPereOriginal != null) {
603
				Node[] ndNodeFils = ndPereOriginal.getChildNodes();
604
 
605
				for (int i = 0; i < ndNodeFils.length; i++) {
606
 
607
					String[] usObj = (String[]) ndNodeFils[i].getUserObject();
608
					TreeNode child = new TreeNode(usObj[0]);
318 aurelien 609
					child.setId(usObj[1]);
155 aurelien 610
					child.setUserObject(usObj);
611
					ndPereCopie.appendChild(child);
612
 
613
					if (!ndNodeFils[i].isLeaf()) {
614
						copierFilsNoeud(ndNodeFils[i], child);
615
					}
616
 
617
				}
618
			}
619
		}
318 aurelien 620
 
621
		public void raz() {
622
 
623
		}
624
 
625
		public boolean renvoyerEtatFiltre() {
626
			// TODO Auto-generated method stub
627
			return false;
628
		}
629
 
630
		public String renvoyerNomFiltre() {
631
			// TODO Auto-generated method stub
632
			return null;
633
		}
634
 
635
		public String[] renvoyerValeursAFiltrer() {
335 aurelien 636
 
637
			String val = motsClesEnCours;
638
 
639
			String[] valeursFiltres = {"mots_cles", val};
640
 
641
			GWT.log(val);
642
 
643
			return valeursFiltres;
318 aurelien 644
		}
645
 
646
		public void valider() {
647
			// TODO Auto-generated method stub
648
 
649
		}
155 aurelien 650
}