Subversion Repositories eFlore/Applications.cel

Rev

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