Subversion Repositories eFlore/Archives.cel-v2

Rev

Rev 47 | Details | Compare with Previous | Last modification | View Log | RSS feed

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