Subversion Repositories eFlore/Applications.cel

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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