Subversion Repositories eFlore/Applications.cel

Rev

Rev 2615 | 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.image;
2 aperonnet 2
 
2615 aurelien 3
import org.tela_botanica.client.i18n.Msg;
2 aperonnet 4
import org.tela_botanica.client.image.ImageMediateur;
60 jpm 5
import org.tela_botanica.client.interfaces.ListePaginable;
2 aperonnet 6
import org.tela_botanica.client.interfaces.Rafraichissable;
7
import org.tela_botanica.client.interfaces.VueListable;
195 david 8
import org.tela_botanica.client.vues.BarrePaginationVue;
2 aperonnet 9
 
10
import com.google.gwt.user.client.Element;
81 jpm 11
import com.google.gwt.user.client.ui.HTML;
134 aurelien 12
import com.gwtext.client.core.EventCallback;
2 aperonnet 13
import com.gwtext.client.core.EventObject;
134 aurelien 14
import com.gwtext.client.core.Ext;
15
import com.gwtext.client.core.ExtElement;
2 aperonnet 16
import com.gwtext.client.core.XTemplate;
17
import com.gwtext.client.data.FieldDef;
18
import com.gwtext.client.data.IntegerFieldDef;
19
import com.gwtext.client.data.Record;
20
import com.gwtext.client.data.RecordDef;
21
import com.gwtext.client.data.Store;
22
import com.gwtext.client.data.StringFieldDef;
5 aperonnet 23
import com.gwtext.client.dd.DragData;
24
import com.gwtext.client.dd.DragSource;
25
import com.gwtext.client.dd.DropTarget;
26
import com.gwtext.client.dd.DropTargetConfig;
2 aperonnet 27
import com.gwtext.client.util.Format;
28
import com.gwtext.client.widgets.Component;
134 aurelien 29
import com.gwtext.client.widgets.Container;
2 aperonnet 30
import com.gwtext.client.widgets.DataView;
31
import com.gwtext.client.widgets.Panel;
32
import com.gwtext.client.widgets.event.ContainerListenerAdapter;
33
import com.gwtext.client.widgets.event.DataViewListenerAdapter;
146 aurelien 34
import com.gwtext.client.widgets.event.PanelListenerAdapter;
5 aperonnet 35
import com.gwtext.client.widgets.grid.GridDragData;
2 aperonnet 36
 
37
/**
5 aperonnet 38
 * Galerie d'images miniatures Avec barre de pagination
39
 *
2 aperonnet 40
 * @author aurelien
41
 */
5 aperonnet 42
public class GalerieImageVue extends Panel implements Rafraichissable,
60 jpm 43
		VueListable, ListePaginable {
2 aperonnet 44
 
45
	/**
46
	 * instance du médiateur
5 aperonnet 47
	 */
48
	private ImageMediateur iMediateur = null;
2 aperonnet 49
	/**
5 aperonnet 50
	 * Dataview, littéralement "vue de données" qui permet de définir la manière
51
	 * d'afficher les données
52
	 */
53
	private DataView dView = null;
2 aperonnet 54
	/**
5 aperonnet 55
	 * Dataview, littéralement "vue de données" qui permet de définir la manière
56
	 * d'afficher les données
57
	 */
58
	private Store st = null;
2 aperonnet 59
	/**
5 aperonnet 60
	 * Barre de pagination gérant l'affichage d'un nombre donné d'élements par
61
	 * page et la navigation entre eux
62
	 */
59 david 63
	private BarrePaginationVue pt = null;
2 aperonnet 64
	/**
65
	 * Booleen indiquant si la galerie est instanciée ou pas
5 aperonnet 66
	 */
67
	private boolean estInstancie = false;
140 aurelien 68
 
208 aurelien 69
	private boolean garderRatio = true;
140 aurelien 70
 
71
	private int tailleOr = 100 ;
146 aurelien 72
 
73
	boolean lienUploadInitialise = false ;
74
 
75
	HTML videPanel = null ;
2 aperonnet 76
 
146 aurelien 77
 
2 aperonnet 78
	/**
79
	 * Constructeur sans argument, privé car ne doit pas être utilisé
80
	 */
81
	@SuppressWarnings("unused")
5 aperonnet 82
	private GalerieImageVue() {
83
		super();
2 aperonnet 84
	}
5 aperonnet 85
 
2 aperonnet 86
	/**
87
	 * Constructeur avec argument
5 aperonnet 88
	 *
89
	 * @param im
90
	 *            le médiateur avec lequel la vue va communiquer
2 aperonnet 91
	 */
92
	public GalerieImageVue(ImageMediateur im) {
2615 aurelien 93
		super(Msg.get("galerie"));
2 aperonnet 94
		iMediateur = im;
146 aurelien 95
 
2 aperonnet 96
		// on ajoute des listeners au composant tout entier
97
		this.addListener(new ContainerListenerAdapter() {
98
 
5 aperonnet 99
			// pour gagner du temps on n'instancie la vue en elle même que lors
100
			// du premier affichage (lazy rendering)
1292 aurelien 101
			@Override
2 aperonnet 102
			public void onShow(Component component) {
103
 
104
				if (!estInstancie) {
105
					initialiser();
106
				}
134 aurelien 107
 
108
			}
2 aperonnet 109
		});
146 aurelien 110
 
111
		AjouterListenersLiens();
5 aperonnet 112
 
2 aperonnet 113
		// et on ajoute la tool bar
60 jpm 114
		pt = new BarrePaginationVue(this);
2623 aurelien 115
		pt.setLabelElement(Msg.get("images"));
59 david 116
		pt.setTaillePageParDefaut(50);
5 aperonnet 117
		this.setBottomToolbar(pt);
2 aperonnet 118
 
119
	}
120
 
121
	/**
5 aperonnet 122
	 * Ajoute tous les listeners nécessaires à l'intercation utilisateur avec la
123
	 * vue de données
2 aperonnet 124
	 */
125
	public void ajouterListenersDataView() {
126
 
127
		// ajout de listeners pour la gestion de la selection
128
		// dans la galerie
146 aurelien 129
 
2 aperonnet 130
		dView.addListener(new DataViewListenerAdapter() {
5 aperonnet 131
 
2 aperonnet 132
			// gestion du clic sur une image
5 aperonnet 133
 
1292 aurelien 134
			@Override
2 aperonnet 135
			public void onClick(DataView source, int index, Element node,
136
					EventObject e) {
146 aurelien 137
 
2 aperonnet 138
				// on en notifie le médiateur
139
				getIMediateur().clicGalerieImage(index, node, e);
140
 
141
			}
142
 
143
			// gestion du clic droit
5 aperonnet 144
 
1292 aurelien 145
			@Override
2 aperonnet 146
			public void onContextMenu(DataView source, int index, Element node,
147
					EventObject e) {
148
 
5 aperonnet 149
				// on stoppe l'évenement
2 aperonnet 150
				e.stopEvent();
151
				// et on notifie le médiateur
152
				getIMediateur().montrerContextMenu(e);
153
 
154
			}
155
 
156
			// gestion du double clic
5 aperonnet 157
 
1292 aurelien 158
			@Override
2 aperonnet 159
			public void onDblClick(DataView source, int index, Element node,
160
					EventObject e) {
161
 
162
				// on notife le mediateur
163
				getIMediateur().clicGalerieImage(index, node, e);
5 aperonnet 164
 
2 aperonnet 165
			}
166
 
167
			// gestion des actions en fonction de la selection
5 aperonnet 168
 
1292 aurelien 169
			@Override
2 aperonnet 170
			public void onSelectionChange(DataView view, Element[] selections) {
171
 
172
				// s'il n'y a aucun élement sélectionné
173
				if (selections.length <= 0) {
174
					// on en notifie le médiateur
175
					getIMediateur().aucuneSelection();
176
				} else {
177
					// sinon on notifie le médiateur
178
					getIMediateur().selection();
5 aperonnet 179
					// et on lui demande de synchroniser la séléction avec les
180
					// autres vues
2 aperonnet 181
					getIMediateur().synchroniserSelection("galerie");
182
				}
183
			}
184
		});
185
	}
186
 
187
	/**
188
	 * Accesseur pour la dataview
5 aperonnet 189
	 *
190
	 * @return la dataview
2 aperonnet 191
	 */
192
	public DataView getDView() {
193
		return dView;
194
	}
195
 
196
	/**
197
	 * Renvoie les ids des images sélectionnées
5 aperonnet 198
	 *
199
	 * @return un tableau de String contenant les identifiants des images
200
	 *         sélectionnées
2 aperonnet 201
	 */
1292 aurelien 202
	@Override
2 aperonnet 203
	public String[] getIdSelectionnees() {
204
		Record[] selection = getDView().getSelectedRecords();
205
		int taille = selection.length;
206
		String id_selection[] = new String[taille];
207
 
208
		for (int i = 0; i < selection.length; i++) {
209
 
1832 aurelien 210
			id_selection[i] = selection[i].getAsString("num_image");
2 aperonnet 211
		}
212
 
213
		return id_selection;
214
	}
215
 
216
	/**
217
	 * Accesseur pour le médiateur
5 aperonnet 218
	 *
2 aperonnet 219
	 * @return le médiateur associé à la vue
220
	 */
221
	public ImageMediateur getIMediateur() {
222
		return iMediateur;
223
	}
224
 
225
	/**
226
	 * Accesseur pour le store
5 aperonnet 227
	 *
2 aperonnet 228
	 * @return le store associé à la vue
229
	 */
230
	public Store getSt() {
231
		return st;
232
	}
5 aperonnet 233
 
2 aperonnet 234
	/**
5 aperonnet 235
	 * Accesseur pour la toolbar
236
	 *
2 aperonnet 237
	 * @return la toolbar associée à la vue
238
	 */
59 david 239
	public BarrePaginationVue getToolBarVue() {
5 aperonnet 240
		return pt;
2 aperonnet 241
	}
242
 
243
	/**
5 aperonnet 244
	 * Fonction d'initialisation du contenu (appelée lors du premier affichage
245
	 * de la liste)
2 aperonnet 246
	 */
247
	public void initialiser() {
5 aperonnet 248
 
2 aperonnet 249
		// Preparation de la dataview et du template
250
		// le template va créer une div contenant une image
251
		// pour chacune des photos
252
		final XTemplate template = new XTemplate(
253
				new String[] {
254
						"<tpl for='.'>",
255
						"<div class='thumb-wrap' id='{num_image}'>",
408 aurelien 256
						"<div class='thumb dview-list'>{indication_transmission}{indication_liaison}<img class='miniature_galerie' src='{url_image_M}' width='{taille_x_s} px' height='{taille_y_s} px' title='{infobulle}' /></div>",
401 aurelien 257
						"<span class='info_image'>{nom_obs_associees_formatees}</span></div>", "</tpl>",
2 aperonnet 258
						"<div class='x-clear'></div>" });
5 aperonnet 259
		// pour des raisons de performances on compile le template en une
260
		// fonction
2 aperonnet 261
		template.compile();
262
 
263
		// la dataview affichera les images en accord avec le template
264
		// cree precedemment
265
		dView = new DataView("div.thumb-wrap") {
266
 
1292 aurelien 267
			@Override
2 aperonnet 268
			public void prepareData(Data data) {
269
				data.setProperty("shortName", Format.ellipsis(data
208 aurelien 270
						.getProperty("nom_original"), 15));
140 aurelien 271
 
272
				int[] XY = {data.getPropertyAsInt("taille_x") ,data.getPropertyAsInt("taille_y")} ;
273
				int[] XYresize ;
274
 
275
				if(garderRatio) {
276
					XYresize = calculerDimensions(XY);
277
				}
278
				else {
279
					XYresize = new int[2] ;
280
					XYresize[0] = XYresize[1] = tailleOr ;
281
 
282
				}
283
 
284
				data.setProperty("taille_x_s", XYresize[0]);
285
				data.setProperty("taille_y_s", XYresize[1]);
401 aurelien 286
 
287
				String nomObs = data.getProperty("obs_associees");
408 aurelien 288
 
401 aurelien 289
				String htmltransmis = "";
290
				String htmllie = "";
408 aurelien 291
 
292
				boolean associee = estAssocieeTransmise(nomObs)[0];
293
				boolean transmise = estAssocieeTransmise(nomObs)[1];
294
 
295
				String nomFormate = getNomsObservationsFormatees(nomObs);
296
 
297
				if(associee) {
298
					htmllie = "<img class='picto_haut_droite' src='chain.png' />";
401 aurelien 299
				}
408 aurelien 300
 
301
				if(transmise) {
302
					htmltransmis = "<img class='picto_haut_gauche' src='tela.png' />";
303
				}
401 aurelien 304
 
408 aurelien 305
				data.setProperty("infobulle", nomFormate);
401 aurelien 306
				data.setProperty("indication_transmission", htmltransmis);
307
				data.setProperty("indication_liaison", htmllie);
408 aurelien 308
				data.setProperty("nom_obs_associees_formatees", nomFormate);
401 aurelien 309
 
2 aperonnet 310
			}
311
		};
312
		dView.setTpl(template);
313
 
314
		// parametre d'affichage de la dataview
315
		this.setAutoScroll(true);
316
		dView.setAutoHeight(true);
317
		dView.setMultiSelect(true);
318
		dView.setOverCls("x-view-over");
146 aurelien 319
		dView.setEmptyText("");
2 aperonnet 320
 
321
		// creation du store
322
		FieldDef defNumImage = new IntegerFieldDef("num_image");
208 aurelien 323
		FieldDef defNomImage = new StringFieldDef("nom_original");
2 aperonnet 324
		FieldDef defDatImage = new StringFieldDef("dat_image");
325
		FieldDef defLieImage = new StringFieldDef("lie_image");
326
		FieldDef defAppImage = new StringFieldDef("app_image");
327
		FieldDef defUrlImageS = new StringFieldDef("url_image_S");
328
		FieldDef defUrlImageM = new StringFieldDef("url_image_M");
329
		FieldDef defUrlImage = new StringFieldDef("url_image");
140 aurelien 330
		FieldDef defTailleX = new IntegerFieldDef("taille_x");
331
		FieldDef defTailleY = new IntegerFieldDef("taille_y");
401 aurelien 332
		FieldDef defObsAssociees = new StringFieldDef("obs_associees");
208 aurelien 333
		FieldDef[] defTab = { defNumImage, defNomImage, defDatImage, defLieImage,
401 aurelien 334
				defAppImage, defUrlImageS, defUrlImageM, defUrlImage,defTailleX,defTailleY, defObsAssociees};
2 aperonnet 335
		RecordDef rd = new RecordDef(defTab);
336
		st = new Store(rd);
337
		dView.setStore(st);
338
 
2623 aurelien 339
		this.getDView().setLoadingText(Msg.get("chargement"));
2 aperonnet 340
 
146 aurelien 341
		this.add(dView);
342
		dView.hide();
2615 aurelien 343
		videPanel = new HTML("<div class=\"avertissement\" >"+Msg.get("avertissement-aucune-image")+". <br/> <a id=\"lienUploadMultiple\" href=\"#\" > "+Msg.get("cliquez-plusieurs-fichiers-images-fois")+" </a> ("+Msg.get("necessite-java")+") <br/> " +
344
				"			<a id=\"lienUploadSimple\" href=\"#\" > "+Msg.get("cliquez-un-fichier-image-fois")+" </a> <br/> " +
345
				"			"+Msg.get("indication-ajouter-images-plus-tard")+" </div>");
146 aurelien 346
		this.add(videPanel);
347
 
2 aperonnet 348
		// ajouts de la gestion des evenements pour la dataview
146 aurelien 349
		configDragAndDrop() ;
2 aperonnet 350
		ajouterListenersDataView();
146 aurelien 351
 
352
		estInstancie = true ;
353
 
2 aperonnet 354
	}
5 aperonnet 355
 
356
	public void configDragAndDrop()
357
	{
358
		// on fabrique la nouvelle configuration
359
		// les éléments sur lesquels on fait du drag 'n drop doivent tous avoir le même ddGroup
360
		DropTargetConfig dtc = new DropTargetConfig();
361
		dtc.setdDdGroup("DragGroupName");
2 aperonnet 362
 
5 aperonnet 363
		//La drop target permet de gérer l'évenement onDrop sur l'élement courant
364
		@SuppressWarnings("unused")
365
		DropTarget tg = new DropTarget(this, dtc)
366
		{
1292 aurelien 367
			@Override
5 aperonnet 368
			public boolean notifyDrop(DragSource source, EventObject e, DragData data){
369
 
370
				// si les données proviennent d'une grille
371
				if(data instanceof GridDragData)
372
		    	{
373
					// on appelle le médiateur
374
		    		  	return iMediateur.lierObsDD(source, e, data,getId()) ;
375
		    	}
376
				return false ;
377
			}
378
 
1292 aurelien 379
			@Override
5 aperonnet 380
			public String notifyOver(DragSource source, EventObject e, DragData data){
381
			    return "x-dd-drop-ok";
382
			}
383
		};
384
 
385
	}
386
 
2 aperonnet 387
	/**
388
	 * Méthode héritée de l'interface rafraichissable
389
	 */
1292 aurelien 390
	@Override
2 aperonnet 391
	public void rafraichir(Object nouvelleDonnees,
392
			boolean repandreRafraichissement) {
393
 
394
		// si l'objet reçu est un store
395
		if (nouvelleDonnees instanceof Store) {
5 aperonnet 396
 
134 aurelien 397
				st = (Store) nouvelleDonnees;
398
 
399
			if(st.getCount() != 0) {
400
 
401
				// on le charge
402
				st.load();
403
 
595 aurelien 404
				if(videPanel != null && videPanel.isVisible()) {
146 aurelien 405
					videPanel.setVisible(false) ;
406
				}
407
 
638 aurelien 408
				if(dView != null) {
409
					if(!dView.isVisible()) {
410
						dView.setVisible(true);
411
					}
412
						// on l'affecte à la vue
413
						dView.setStore(st);
414
						// et on rafrachit la vue
415
						dView.refresh();
146 aurelien 416
				}
134 aurelien 417
			}
140 aurelien 418
			else
419
			{
420
				st.removeAll();
421
				st.load();
422
				dView.setStore(st);
146 aurelien 423
 
424
				if(dView.isVisible()) {
425
					dView.hide() ;
426
				}
427
 
595 aurelien 428
				if(videPanel != null && !videPanel.isVisible()) {
146 aurelien 429
					videPanel.setVisible(true);
430
					AjouterListenersLiens();
431
				}
432
 
140 aurelien 433
			}
2 aperonnet 434
		}
435
 
436
		// si le composant doit répandre le rafraichissement
437
		if (repandreRafraichissement) {
5 aperonnet 438
			// il en notifie le médiateur en lui donnant une copie des données
439
			// et en notifiant qu'il en est l'expéditeur
2 aperonnet 440
			getIMediateur().synchroniserDonneesZoomListeGalerie(
441
					nouvelleDonnees, this);
146 aurelien 442
		}
2 aperonnet 443
	}
444
 
445
	/**
5 aperonnet 446
	 * Méthode héritée de l'interface VueListable Sélectionne les images dans la
447
	 * galerie suivant les identifiants donnés en paramètres
448
	 *
449
	 * @param ids
450
	 *            les identifiants des images à sélectionner
2 aperonnet 451
	 */
452
	public void selectionnerImages(int[] ids) {
453
 
454
		getDView().select(ids);
455
 
456
	}
5 aperonnet 457
 
1292 aurelien 458
	@Override
60 jpm 459
	public void changerNumeroPage(int pageCourante) {
460
 
461
		iMediateur.changerNumeroPage(pageCourante) ;
462
 
463
	}
464
 
1292 aurelien 465
	@Override
60 jpm 466
	public void changerTaillePage(int nouvelleTaillePage) {
467
 
468
		iMediateur.changerTaillePage(nouvelleTaillePage) ;
469
	}
140 aurelien 470
 
471
	public int[] calculerDimensions(int[] tailleXY) {
472
 
473
		float[] tailleXYf = {new Float(tailleXY[0]),new Float(tailleXY[1])} ;
474
        float tailleOr = this.tailleOr ;
475
        float maxTaille = Math.max(tailleXYf[1],tailleXYf[0]) ;
476
        float[] XYresize = new float[2];
477
 
478
        if(maxTaille == tailleXY[0]) {
479
            float rapport = tailleXYf[1]/tailleXYf[0] ;
480
            XYresize[0] = tailleOr ;
481
            XYresize[1] = tailleOr*rapport ;
482
        }else {
483
            float rapport = tailleXYf[0]/tailleXYf[1] ;
484
            XYresize[1] = tailleOr ;
485
            XYresize[0] = tailleOr*rapport ;
486
        }
487
 
488
        int[] res = {Math.round(XYresize[0]),Math.round(XYresize[1])} ;
489
 
490
        return res;
491
    }
146 aurelien 492
 
493
	private void AjouterListenersLiens() {
60 jpm 494
 
146 aurelien 495
		addListener(new PanelListenerAdapter() {
496
 
1292 aurelien 497
			@Override
146 aurelien 498
			public void onAfterLayout(Container c) {
499
				ExtElement uploadS = Ext.get("lienUploadSimple");
500
				uploadS.removeAllListeners();
501
				uploadS.addListener("click", new EventCallback() {
1292 aurelien 502
					@Override
146 aurelien 503
					public void execute(EventObject e) {
504
						getIMediateur().uploaderImages(false);
505
					}
506
 
507
				}) ;
508
 
509
				ExtElement uploadM = Ext.get("lienUploadMultiple");
510
				uploadM.removeAllListeners();
511
				uploadM.addListener("click", new EventCallback() {
1292 aurelien 512
					@Override
146 aurelien 513
					public void execute(EventObject e) {
514
						getIMediateur().uploaderImages(true);
515
					}
516
				});
517
			}
518
 
519
		});
520
	}
408 aurelien 521
 
522
	private String getNomsObservationsFormatees(String nomObs) {
523
 
524
		String htmlInfobulle = "";
525
 
526
		String[][] obs = getObservationsAssociees(nomObs);
527
 
528
		for(int i = 0; i < obs.length; i++) {
529
			if(obs[i].length == 3 && obs[i][1] != null && !obs[i][1].equals("")) {
530
				htmlInfobulle += ", "+obs[i][1];
531
			}
532
		}
533
 
534
		htmlInfobulle = htmlInfobulle.replaceFirst(", ", "");
535
 
536
		return htmlInfobulle;
537
	}
538
 
539
	private String[][] getObservationsAssociees(String nomObs) {
540
 
541
		if(nomObs.trim().equals("")) {
542
			return new String[0][0];
543
		}
544
 
545
		String[] obsTab = nomObs.split(";;");
546
		String[][] obsAnalysees = new String[obsTab.length][3];
547
 
548
		for(int i = 0; i < obsTab.length; i++) {
549
 
550
			obsAnalysees[i] = obsTab[i].split("#");
551
 
552
		}
553
 
554
		return obsAnalysees;
555
	}
556
 
557
	private boolean[] estAssocieeTransmise(String nomObs) {
558
 
559
		String[][] obs = getObservationsAssociees(nomObs);
560
		boolean[] associeesTranmises = {false, false};
561
 
562
		if(obs.length > 0) {
563
			associeesTranmises[0] = true;
564
		}
565
 
566
		for(int i = 0; i < obs.length; i++) {
567
 
568
			if(obs[i].length == 3 && obs[i][2] != null && obs[i][2].equals("1")) {
569
				associeesTranmises[1] = true;
570
			}
571
		}
572
 
573
		return associeesTranmises;
574
	}
2 aperonnet 575
}