Subversion Repositories eFlore/Applications.cel

Rev

Rev 173 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package org.tela_botanica.client.image;


import org.tela_botanica.client.CarnetEnLigneMediateur;
import org.tela_botanica.client.interfaces.IdVue;
import org.tela_botanica.client.interfaces.ListePaginable;
import org.tela_botanica.client.interfaces.Rafraichissable;
import org.tela_botanica.client.interfaces.VueListable;
import org.tela_botanica.client.modeles.Configuration;
import org.tela_botanica.client.modeles.ListeObservation;
import org.tela_botanica.client.observation.ObservationMediateur;
import org.tela_botanica.client.vues.ArbreMotsClesObsFiltreVue;
import org.tela_botanica.client.vues.ArbreMotsClesVue;
import org.tela_botanica.client.vues.BarreOutilsVue;
import org.tela_botanica.client.vues.BarreRechercheFiltreVue;
import org.tela_botanica.client.vues.GalerieImageVue;
import org.tela_botanica.client.vues.ListeImageVue;
import org.tela_botanica.client.vues.MenuImageVue;
import org.tela_botanica.client.vues.MiniListeObservationVue;
import org.tela_botanica.client.vues.PanneauFiltresImagesVues;
import org.tela_botanica.client.vues.PanneauMetadonneesVue;
import org.tela_botanica.client.vues.ZoomImageVue;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTML;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.Ext;
import com.gwtext.client.core.ExtElement;
import com.gwtext.client.core.RegionPosition;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.Store;
import com.gwtext.client.data.Tree;
import com.gwtext.client.dd.DragData;
import com.gwtext.client.dd.DragSource;
import com.gwtext.client.widgets.BoxComponent;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.Container;
import com.gwtext.client.widgets.DataView;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.TabPanel;
import com.gwtext.client.widgets.MessageBox.AlertCallback;
import com.gwtext.client.widgets.event.ComponentListenerAdapter;
import com.gwtext.client.widgets.event.ContainerListener;
import com.gwtext.client.widgets.event.ContainerListenerAdapter;
import com.gwtext.client.widgets.event.PanelListener;
import com.gwtext.client.widgets.event.PanelListenerAdapter;
import com.gwtext.client.widgets.grid.GridDragData;
import com.gwtext.client.widgets.layout.BorderLayout;
import com.gwtext.client.widgets.layout.BorderLayoutData;
import com.gwtext.client.widgets.layout.FitLayout;
import com.gwtext.client.widgets.menu.BaseItem;
import com.gwtext.client.widgets.menu.Item;
import com.gwtext.client.widgets.menu.Menu;
import com.gwtext.client.widgets.menu.event.MenuListenerAdapter;
import com.gwtext.client.widgets.tree.TreeEditor;
import com.gwtext.client.widgets.tree.TreeNode;

/**
 * Mediateur gérant les interactions entre vues et les echanges de données C'est
 * un singleton.
 * 
 * @author aurelien
 * 
 */

// TODO : Deporter les methodes de ListePaginable dans la liste  d'images

public class ImageMediateur implements ListePaginable{

        /**
         * le mediateur des observations qui lie la partie images au carnet
         */
        private CarnetEnLigneMediateur cMediateur = null;

        
        private static ImageMediateur thisMediateur = null ;
        /**
         * booleen qui verifie l'unicite de l'instance (donc static)
         */
        private static boolean estInstancie = false;

        /**
         * modele de données
         */
        private ImageModele iModele = null;

        /**
         * L'identifiant utilisateur. Par défaut, il vaut 0
         */
        private String identifiant = "0";

        /**
         * panneau principal des images (onglet "images")
         */
        private Panel panneauPrincipalImage = null ;

        /**
         * panneau a onglet pour la liste, la galerie et la vue en grand
         */
        private TabPanel ongletsImage = null;

        /**
         * panneau de filtrage
         */
        private PanneauFiltresImagesVues filtres = null;

        /**
         * conteneur du panneau a onglets
         */
        private Panel panneauMenuEtOngletsImage = null;

        /**
         * galerie de miniature
         */
        private GalerieImageVue galerieImage = null;

        /**
         * liste détaillée des images
         */
        private ListeImageVue listeImage = null;

        /**
         * vue agrandie de la l'image selectionnée
         */
        private ZoomImageVue zoomImage = null;

        /**
         * panneau a onglets affichant les métadonnées et les mots clés
         */
        private PanneauMetadonneesVue metadonneesIptcExif = null;

        /**
         * panneau conteneur pour le panneau a onglet des metadonnées
         */
        private final Panel detailsEtMotsCles = new Panel("Détails et mots clés");

        /**
         * menu contextuel de manipulation des images
         */
        private MenuImageVue menuImageVue = null;

        /**
         * barre d'outils
         */
        private BarreOutilsVue barreOutilsVue = null;

        /**
         * l'indice du dernier onglet sélectionné
         */
        private int dernierIndexOnglet = 0;

        /**
         * booleen explicitant s'il y a une selection en cours
         */
        private boolean selection = false;

        /**
         * Filtre pour les mots cles
         */
        private ArbreMotsClesObsFiltreVue filtreMotsCles = null;

        /**
         * Filtre pour les commentaires
         */
        private BarreRechercheFiltreVue filtreCommentaires = null;
        
        /**
         * Boolean indiquand si le médiateur a seulement été crée ou bien si tous
         * les composants ont été crées
         */
        private boolean estInitialise = false;

        /**
         * constructeur privé (on accède a la classe par la méthode getInstance)
         */
        private ImageMediateur() {
                                
                                initialiser() ;
        }

        /**
         * constructeur avec paramètres privé (on accède a la classe par la méthode
         * getInstance)
         * 
         * @param cm
         *            le médiateur du carnet à associer à la partie image
         */
        private ImageMediateur(CarnetEnLigneMediateur cm) {
                
                cMediateur = cm;
                panneauPrincipalImage = new Panel("Images") ;
                panneauPrincipalImage.addListener(new PanelListenerAdapter() {
                        public boolean doBeforeRender(Component c) {
                                if(!estInitialise) {
                                        initialiser() ;
                                }
                                return true;
                        }
                });
        }

        /**
         * Change la valeur du booleen de selection
         * 
         * @param selection
         *            la nouvelle valeur du booléen
         */
        public void setSelection(boolean selection) {
                this.selection = selection;
        }

        /**
         * renvoie la valeur du booleen de selection
         * 
         * @return la valeur du booleen de selection
         */
        public boolean isSelection() {
                return selection;
        }

        /**
         * Retourne une instance de manière unique
         * 
         * @return l'instance unique du médiateur
         */
        public static ImageMediateur Instance() {
                if (!estInstancie && thisMediateur == null) {
                        // on en crée un nouveau
                        estInstancie = true;
                        thisMediateur = new ImageMediateur();
                }
                // sinon on retourne le "pointeur" vers le médiateur lui-même
                return thisMediateur;
        }

        /**
         * Retourne une instance de manière unique en lui associant un médiateur
         * pour les observations
         * 
         * @param cm le médiateur de carnet à associer
         * @return l'instance unique du médiateur
         */
        public static ImageMediateur Instance(CarnetEnLigneMediateur cm) {
                if (!estInstancie && thisMediateur == null) {
                        // on en crée un nouveau
                        estInstancie = true;
                        thisMediateur = new ImageMediateur(cm);
                }
                // sinon on retourne le "pointeur" vers le médiateur lui-même
                return thisMediateur;
        }
        
        private void initialiser()
        {
                // quelques variables de position pour les borderlayouts
                final BorderLayoutData regionNord = new BorderLayoutData(
                                RegionPosition.NORTH);

                final BorderLayoutData regionCentre = new BorderLayoutData(
                                RegionPosition.CENTER);

                final BorderLayoutData regionEst = new BorderLayoutData(
                                RegionPosition.EAST);
                regionEst.setSplit(true);

                final BorderLayoutData regionOuest = new BorderLayoutData(
                                RegionPosition.WEST);
                regionOuest.setSplit(true);
                
                panneauPrincipalImage.setSize(cMediateur.getPanneauPrincipalCarnetEnLigne().getWidth(), cMediateur.getPanneauPrincipalCarnetEnLigne().getHeight()) ;
                panneauPrincipalImage.setLayout(new BorderLayout()) ;

                // on crée un modèle
                iModele = ImageModele.Instance(this);
                // et on demande l'arbre des mots clés

                // on gère la mise en page du panneau principal

                // on crée le panneau des filtres
                filtres = new PanneauFiltresImagesVues(this);
                filtres.setWidth("15%");

                // le panneau à onglet qui contient les trois vues
                ongletsImage = new TabPanel();

                // la galerie
                galerieImage = new GalerieImageVue(this);

                // la liste des images
                listeImage = new ListeImageVue(this);
                listeImage.setTitle("Liste") ;

                // le panneau zoom
                zoomImage = new ZoomImageVue(this);

                // on ajoute les panneaux au panneau à onglets
                ongletsImage.add(galerieImage);
                ongletsImage.add(listeImage);
                ongletsImage.add(zoomImage);

                // on crée les menu et la barre de vue
                menuImageVue = new MenuImageVue(this);
                barreOutilsVue = new BarreOutilsVue(this);

                // on initialise le volet qui contient les mots clés
                detailsEtMotsCles.setWidth("15%");
                detailsEtMotsCles.setAnimCollapse(true);
                detailsEtMotsCles.setTitleCollapse(true);
                detailsEtMotsCles.setCollapsible(true);

                // on crée le panneau conteneur des métadonnées et infos
                metadonneesIptcExif = new PanneauMetadonneesVue(this);
                // et on l'inclut dans le volet approprié
                detailsEtMotsCles.add(metadonneesIptcExif);
                

                panneauMenuEtOngletsImage = new Panel() ;
                panneauMenuEtOngletsImage.setLayout(new BorderLayout()) ;
                // on ajoute la barre de vue au nord du panneau qui contient menu et
                // onglets d'images
                panneauMenuEtOngletsImage.add(barreOutilsVue, regionNord);
                // les onglets au centre
                panneauMenuEtOngletsImage.add(ongletsImage, regionCentre);
                
                // et le panneau de métadonnées et d'info sur le coté droit
                panneauPrincipalImage.add(detailsEtMotsCles, regionEst);
                
                // on ajoute le panneau qui contient le menu et les onglets d'images au
                // centre
                panneauPrincipalImage.add(panneauMenuEtOngletsImage, regionCentre);
                
                // on ajoute les filtres au panneau gauche
                panneauPrincipalImage.add(filtres,regionOuest) ;
                
                detailsEtMotsCles.addListener(new ContainerListenerAdapter() {

                        public void onResize(BoxComponent component,int adjWidth,int adjHeight,int rawWidth,int rawHeight)
                        {
                                if(detailsEtMotsCles != null && detailsEtMotsCles.isRendered() && metadonneesIptcExif != null && metadonneesIptcExif.isRendered()) {
                                        metadonneesIptcExif.doLayout();
                                }
                        }
                });
                
                // filtres.setCollapsed(false) ;
                thisMediateur = this ;
                
                estInitialise = true ;
                
                changerUtilisateur() ;
        }

        /**
         * Renvoie l'identifiant de l'utilisateur en cours
         * 
         * @return l'identifiant de l'utilisateur
         */
        public String getIdentifiant() {
                
                return cMediateur.getUtilisateur().getIdentite();
        
        }

        /**
         * . Setteur pour l'identifiant de l'utilisateur en cours
         * 
         * @param id
         *            le nouvel identifiant utilisateur
         */
        public void setIdentifiant(String id) {
                identifiant = id;
        }

        /**
         * Appelle les fonctions de chargement de données, suit généralement un
         * appel à setIdentifiant, pour obtenir l'arbre des mots clés et les images
         * du nouvel utilisateur
         */
        public void changerUtilisateur() {
                getIModele().initialiserArbreMotsCles();
                obtenirPhotoGalerie(getGalerieImage());
        }

        /**
         * Accesseur pour le modèle associé au médiateur
         * 
         * @return le modèle associé
         */
        public ImageModele getIModele() {
                return iModele;
        }

        /**
         * Accesseur pour le panneau principal
         * 
         * @return le panneau principal
         */
        public Panel getPanneauPrincipalImage() {
                return panneauPrincipalImage;
        }

        /**
         * Accesseur pour le panneau à onglets
         * 
         * @return le panneau à onglets
         */
        public TabPanel getOngletsImage() {
                return ongletsImage;
        }

        /**
         * Accesseur pour la galerie d'images
         * 
         * @return la galerie d'image
         */
        public GalerieImageVue getGalerieImage() {
                return galerieImage;
        }

        public ListeImageVue getListeImage() {
                return listeImage;
        }

        /**
         * Accesseur pour le panneau "zoom"
         * 
         * @return le panneau zoom
         */
        public ZoomImageVue getZoomImage() {
                return zoomImage;
        }

        /**
         * Accesseur pour le panneau détails et mot clés
         * 
         * @return le panneau détails et mots clés
         */
        public Panel getDetailsEtMotsCles() {
                return detailsEtMotsCles;
        }

        /**
         * Accesseur pour le booleen d'instanciation
         * 
         * @return le booleen d'instanciation
         */
        public static boolean isEstInstancie() {
                return estInstancie;
        }

        /**
         * Accesseur pour la panneau contenant le menu et les onglets images
         * 
         * @return le panneauMenuEtOngletsImage
         */
        public Panel getPanneauMenuEtOngletsImage() {
                return panneauMenuEtOngletsImage;
        }

        /**
         * Accesseur pour le menu image
         * 
         * @return the menuImageVue
         */
        public MenuImageVue getMenuImageVue() {
                return menuImageVue;
        }

        /**
         * Accesseur pour la barre d'outils
         * 
         * @return the barreOutilsVue
         */
        public BarreOutilsVue getBarreOutilsVue() {
                return barreOutilsVue;
        }

        /**
         * Accesseur pour le panneau infos et métadonnées
         * 
         * @return the metadonneesIptcExif
         */
        public PanneauMetadonneesVue getMetadonneesIptcExif() {
                return metadonneesIptcExif;
        }

        /**
         * Renvoie l'index du dernier onglet sélectionné
         * 
         * @return l'index du dernier onglet
         */
        public int getDernierIndexOnglet() {
                return dernierIndexOnglet;
        }

        /**
         * Accesseur pour l'arbre des filtres
         * 
         * @return l'arbre pour filtrer les mots clés
         */
        public ArbreMotsClesObsFiltreVue getFiltreMotsCles() {
                return filtreMotsCles;
        }

        /**
         * Accesseur pour la barre de recherche
         * 
         * @return la barre de recherche pour filtrer les commentaires
         */
        public BarreRechercheFiltreVue getFiltreCommentaires() {
                return filtreCommentaires;
        }

        /**
         * Renvoie la vue sélectionné par l'utilisateur
         * 
         * @return la vue selectionnée par l'utilisateur
         */
        public VueListable getVueSelectionnee() {
                Panel active = ongletsImage.getActiveTab();
                if (active != zoomImage) {
                        if (active == galerieImage) {
                                return galerieImage;
                        } else {
                                return listeImage;
                        }

                } else {
                        if (dernierIndexOnglet == 0) {
                                return galerieImage;
                        } else {
                                return listeImage;
                        }

                }

        }

        /**
         * Renvoie l'identifiant de la vue en cours
         * 
         * @return l'identifiant de la vue en cours de visualisation
         */
        public String getIdVueSelectionnee() {
                Panel active = ongletsImage.getActiveTab();
                if (active != zoomImage) {
                        if (active == galerieImage) {
                                return galerieImage.getId();
                        } else {
                                return listeImage.getId();
                        }

                } else {
                        if (dernierIndexOnglet == 0) {
                                return galerieImage.getId();
                        } else {
                                return listeImage.getId();
                        }

                }

        }

        /**
         * Met a jour les données provenant du modèle et synchronise les vues entre
         * elles
         * 
         * @param o
         *            données de mises a jour pour les vues
         * @param r
         *            le refraichissable qui a demandé la mise a jour
         */
        public void synchroniserDonneesZoomListeGalerie(Object o, Rafraichissable r) {

                if (o instanceof Store) {

                        Store li = (Store) o;

                        if (li.getCount() <= 0) {
                                aucuneSelection();
                        } else {
                                selection();
                        }

                }

                if (r != getGalerieImage()) {
                        getGalerieImage().rafraichir(o, false);
                }
                if (r != getZoomImage()) {
                        getZoomImage().rafraichir(o, false);
                }
                if (r != getListeImage()) {
                        getListeImage().rafraichir(o, false);
                }

                aucuneSelection();
                demasquerChargement();
        }

        /**
         * envoie au modèle une demande de mise a jour
         * 
         * @param r
         *            la vue demandeuse de mise a jour
         */
        public void obtenirPhotoGalerie(Rafraichissable r) {
                masquerChargement();
                getIModele().obtenirNombrePhotoGalerie(r);
        }

        /**
         * demande au modèle les métadonnées associées a une image
         * 
         * @param r
         *            la vue demandeuse de mise a jour
         * @param id
         *            l'identifiant de l'image
         */
        public void obtenirMetadonnees(Rafraichissable r, String id) {
                getIModele().obtenirMetadonnees(r, id);
        }

        /**
         * demande au modèle les ids des mots clés associés a une image
         * 
         * @param r
         *            la vue demandeuse de mise a jour
         * @param id
         *            l'identifiant de l'image
         */
        public void obtenirMotsClesId(Rafraichissable r, String id) {
                getIModele().obtenirMotsClesId(r, id);
        }

        /**
         * Envoie au modèle une demande pour obtenir l'arbre des mots clés
         * 
         * @param r
         *            le raffraichissable qui a demandé la mise à jour
         */
        public void obtenirArbreMotsCles(Rafraichissable r) {
                getIModele().initialiserArbreMotsCles();
        }

        /**
         * envoie au modèle une demande de mise a jour des informations modifiables
         * associées a une image
         * 
         * @param commentaires
         *            le commentaire de l'image
         * @param date
         *            la date modifiée par l'utilisateur
         */
        public void mettreAJourInfo(String commentaires, String date, String note) {
                String ids[] = getVueSelectionnee().getIdSelectionnees();

                getIModele().mettreAJourCacheImage(commentaires, date, note, ids);
                getListeImage().mettreAjourInfos(commentaires, date, note);
        }

        /**
         * Met à jour l'arbre des mots clés affichés dans le volet de droite à
         * partir de l'arbre passé en paramètre
         * 
         * @param arbreMC
         *            le nouvel arbre des mots clés
         */
        public void rafraichirArbreMotsCles(Tree arbreMC) {
                metadonneesIptcExif.getPanneauMotsCles().rafraichir(arbreMC, false);
                filtres.getMotsClesFiltre().rafraichir(arbreMC, false);
        }

        /**
         * envoie au modèle une demande pour lancer le formulaire ou l'application
         * d'upload
         */
        public void uploaderImages(boolean multiple) {
                if(cMediateur.getUtilisateur().isIdentifie()) {
                        getIModele().uploaderImages(multiple);
                }
                else
                {
                        if(Window.confirm("L'envoi d'images nécéssite d'être identifié. Voulez-vous vous identifier maintenant ?")) {
                                cMediateur.afficherDialogueConnexion();
                        }
                        else
                        {
                                
                        }
                }
        }

        /**
         * Envoie une demande au modèle pour obtenir toutes les données annexes de
         * l'image (métadonnées, note, etc ...), on y centralise tous les appels a
         * obtenirQuelqueChose
         * 
         * @param imgNum
         *            l'identifiant de l'image
         */
        public void obtenirDonnes(String imgNum) {
                obtenirMetadonnees(metadonneesIptcExif, imgNum);
                obtenirMotsClesId(metadonneesIptcExif.getPanneauMotsCles(), imgNum);
                obtenirNote(metadonneesIptcExif.getNoteVue(), imgNum);
                
                if(getMetadonneesIptcExif().getMiniListeObservation().getMode())
                {
                        obtenirObservationsAssociees() ;
                }
                else
                {
                        //TODO: réfléchir : que faire dans cas là ?
                }
        }
        
        public void changerModeLiaison(boolean mode) {
                
                if(mode) {
                        obtenirObservationsAssociees() ;
                }
                else {
                        obtenirMiniListeObservations(getMetadonneesIptcExif().getMiniListeObservation()) ;
                }
        }

        /**
         * Envoie une demande au modèle pour obtenir la note associée à une image
         * 
         * @param noteVue
         *            le rafraichissable à qui est destiné cette information
         * @param imgNum
         *            l'identifiant de l'image
         */
        private void obtenirNote(Rafraichissable r, String imgNum) {

                getIModele().obtenirNote(r, imgNum);
        }

        /**
         * est appelé lors d'un clic de souris sur une vignette dans la galerie le
         * médiateur gère alors les conséquences
         * 
         * @param index
         *            l'index du noeud dans la galerie
         * @param node
         *            le noeud selectionné
         * @param e
         *            l'object source de l'évenement
         */
        public void clicGalerieImage(int index, Element node, EventObject e) {
                Record rd = getGalerieImage().getDView().getRecord(node);
                String imgUrl = rd.getAsString("url_image");
                String imgNum = rd.getAsString("num_image");
                String[] imgXY = getIModele().obtenirTailleImage(
                                rd.getAsString("num_image"));
                String[] infosImage = { imgUrl, imgXY[0], imgXY[1], imgNum };

                getZoomImage().rafraichir(infosImage, false);
                dernierIndexOnglet = 0;

                if (DOM.eventGetType(e.getBrowserEvent()) == Event.ONDBLCLICK) {

                        getOngletsImage().setActiveTab(2);
                }

                obtenirDonnes(imgNum);

        }

        /**
         * est appelé lors d'un clic de souris sur un enregistrement de la liste le
         * médiateur gère alors les conséquences
         * 
         * @param rowIndex
         *            le numéro de ligne selectionné
         */
        public void clicListeImage(int rowIndex) {
                Record rd = getListeImage().getSelectionModel().getSelected();
                String imgUrl = rd.getAsString("url_image");
                String imgNum = rd.getAsString("num_image");
                String[] imgXY = getIModele().obtenirTailleImage(
                                rd.getAsString("num_image"));
                String[] infosImage = { imgUrl, imgXY[0], imgXY[1], imgNum };

                getZoomImage().rafraichir(infosImage, false);

                dernierIndexOnglet = 1;

                obtenirDonnes(imgNum);
        }

        /**
         * gestion du double clic dans la liste
         * 
         * @param rowIndex
         */
        public void doubleClicListeImage(int rowIndex) {
                clicListeImage(rowIndex);
                getOngletsImage().setActiveTab(2);
        }

        /**
         * envoie une demande de mise a jour des données au modèle
         */
        public void rafraichirToutesVues() {
                obtenirPhotoGalerie(getIModele());
        }

        /**
         * montre le menu au coordonnées indiquées
         * 
         * @param e
         *            l'objet source de l'évenement
         */
        public void montrerContextMenu(EventObject e) {
                menuImageVue.showAt(e.getXY());
        }

        /**
         * appelé lors du double clic sur l'image agrandie
         */
        public void doubleClicZoomImage() {
                getOngletsImage().setActiveTab(dernierIndexOnglet);
        }

        /**
         * appelé lors du clic sur un des boutons de la zone zoom
         * 
         * @param arg
         *            le nom du bouton qui a cliqué
         */
        public void clicBoutonZoomImage(String arg) {

                Store st;
                int selected;
                int storeIndex;
                Record nRec = null;

                // tout d'abord on obtient les index selectionnés suivant la vue
                if (getVueSelectionnee() == galerieImage) {
                        DataView dv = getGalerieImage().getDView();
                        st = getGalerieImage().getSt();

                        if (st.getCount() <= 0) {
                                return;
                        }

                        selected = st.indexOf(dv.getSelectedRecords()[0]);
                        storeIndex = dv.indexOf(selected);
                } else {
                        st = listeImage.getSt();

                        if (st.getCount() <= 0) {
                                return;
                        }

                        selected = st.indexOf(listeImage.getSelectionModel().getSelected());
                        storeIndex = selected;
                }

                if (arg.equals("prev")) {
                        // si la photo séléctionnée est la première, on passe a la
                        // dernière
                        if (selected == 0) {
                                storeIndex = st.getCount() - 1;
                                nRec = st.getAt(storeIndex);

                        } else {
                                storeIndex = storeIndex - 1;
                                nRec = st.getAt(storeIndex);
                        }

                }

                if (arg.equals("suiv")) {
                        // si la photo selectionnée est la dernière on passe a la
                        // première
                        if (selected == st.getCount() - 1) {

                                storeIndex = 0;
                                nRec = st.getAt(0);
                        } else {
                                storeIndex = storeIndex + 1;
                                nRec = st.getAt(storeIndex);
                        }
                }

                if (nRec != null) {
                        String imgUrl = nRec.getAsString("url_image");
                        String imgNum = nRec.getAsString("num_image");
                        String[] imgXY = getIModele().obtenirTailleImage(
                                        nRec.getAsString("num_image"));
                        String[] infosImage = { imgUrl, imgXY[0], imgXY[1], imgNum };
                        getZoomImage().rafraichir(infosImage, false);

                        if (getGalerieImage().isRendered()) {
                                getGalerieImage().getDView().select(storeIndex);
                        }

                        if (getListeImage().isRendered()) {
                                getListeImage().getSelectionModel().selectRecords(nRec);
                        }

                        obtenirDonnes(imgNum);
                }
        }

        /**
         * synchronise la selection entre la galerie et la liste
         * 
         * @param string
         *            le nom de la vue qui doit être synchronisee
         */
        public void synchroniserSelection(String string) {

                if (string.equals("galerie") && getDernierIndexOnglet() != 2) {
                        Record[] sel = getGalerieImage().getDView().getSelectedRecords();
                        getListeImage().selectionnerEnregistrements(sel);
                }

                if (string.equals("liste") && getDernierIndexOnglet() != 0) {

                        Record[] sel = getListeImage().getSelectionModel().getSelections();
                        int[] ids = new int[sel.length];

                        for (int i = 0; i < sel.length; i++) {

                                ids[i] = getGalerieImage().getSt().indexOf(sel[i]);
                        }

                        getGalerieImage().selectionnerImages(ids);
                }

        }

        /**
         * fait une demande de suppression des images (en local et en distant) des
         * images selectionnees
         */
        public void supprimerImages() {

                String[] ids = null;

                if (dernierIndexOnglet == 0) {
                        ids = getGalerieImage().getIdSelectionnees();
                } else {
                        ids = getListeImage().getIdSelectionnees();
                }

                if (ids.length > 0) {

                        if (com.google.gwt.user.client.Window
                                        .confirm("Supprimer les images selectionnees ?")) {
                                masquerChargement();
                                getIModele().supprimerImages(ids);
                                aucuneSelection();
                        }
                } else {
                        Window.alert("Impossible de supprimer : aucune image selectionnee");
                }

        }

        /**
         * desactive les onglets de metadonnees et de zoom (dans le cas ou rien
         * n'est selectionne)
         */
        public void aucuneSelection() {

                if (getListeImage().getSelectionModel().getCount() <= 0
                                && getGalerieImage().getDView().getSelectionCount() <= 0) {
                        getZoomImage().disable();
                        getMetadonneesIptcExif().desactiverPanneau();
                        getZoomImage().desactiverPanneau();
                        setSelection(false);
                }

        }

        /**
         * reactive les onglet metadonnees et zoom (lors d'une selection alors qu'il
         * n'y en avait pas)
         */
        public void selection() {

                if (!isSelection()) {
                        getMetadonneesIptcExif().activerPanneau();
                        getZoomImage().activerPanneau();
                        getZoomImage().enable();
                        setSelection(true);
                }
        }

        /**
         * Fait apparaitre le menu contextuel de l'arbre des mots clés au niveau
         * d'un noeud donné
         * 
         * @param n
         *            le noeud ou le menu doit apparaitre
         * @param ev
         *            l'objet contenant les données sur l'évenement
         * @param te
         *            l'éditeur associé à l'arbre qui permet de modifier les
         *            libellés des noeuds
         */
        public void montrerContextMenuArbre(final TreeNode n, EventObject ev,
                        final TreeEditor te) {
                Menu mn = new Menu();
                final com.gwtext.client.widgets.menu.Item ajoutN = new Item(
                                "Ajouter mot cle");
                final com.gwtext.client.widgets.menu.Item suppN = new Item(
                                "Supprimer mot cle");

                mn.addItem(ajoutN);
                mn.addItem(suppN);

                mn.addListener(new MenuListenerAdapter() {

                        public void onItemClick(BaseItem item, EventObject e) {
                                if (item.equals(suppN)) {
                                        getMetadonneesIptcExif().getPanneauMotsCles()
                                                        .supprimerNoeud(n);
                                }
                                if (item.equals(ajoutN)) {
                                        getMetadonneesIptcExif().getPanneauMotsCles().ajouterNoeud(
                                                        n);
                                }
                        }
                });

                mn.showAt(ev.getXY());

        }

        /**
         * Appelle le modèle pour mettre à jour la paire mot-clé / identifiant du
         * mot clé
         * 
         * @param text
         *            le texte du mot clé
         * @param id
         *            l'identifiant du mot clé
         */
        public void mettreAjourMotsClesId(String text, String id) {

                getIModele().mettreAjourMotsClesId(text, id);

        }

        /**
         * Récupère les identifiants des images selectionnés et appelle le modèle
         * pour qu'il mette à jour les associations mots clés/images
         * 
         * @param motsClesEnCours
         *            les mots clés à associer aux images selectionnés séparés par
         *            une ','
         * @param arbreMC
         *            l'arbre des mots clés à mettre à jour
         */
        public void mettreAjourMotsCles(String motsClesEnCours, Tree arbreMC) {

                String[] ids = getGalerieImage().getIdSelectionnees();
                getIModele().mettreAjourMotsCles(ids, motsClesEnCours, arbreMC);

        }

        /**
         * Appelle le médiateur pour qu'il ajoute un mot clé dans l'arbre des mots
         * clés
         * 
         * @param n
         *            le noeud à ajouter à l'arbre
         * @param arbreMC
         *            le nouvel arbre de mots clés à mettre à jour
         */
        public void ajouterMotCleDansArbre(TreeNode n, Tree arbreMC) {
                getIModele().ajouterMotCleDansArbre(n, arbreMC);
                filtres.getMotsClesFiltre().rafraichir(n, false);

        }

        /**
         * Appelle le médiateur pour qu'il supprime un mot clé et son sous arbre
         * dans l'arbre des mots clés
         * 
         * @param n
         *            le noeud à supprimer
         * @param arbreMC
         *            le nouvel arbre de mots clés à mettre à jour
         */
        public void supprimerMotCleDansArbre(TreeNode n, Tree arbreMC) {

                getIModele().supprimerMotCleDansArbre(n, arbreMC);
                filtres.getMotsClesFiltre().rafraichir(n.getId(), false);

        }

        /**
         * Appelle le médiateur pour qu'il modifie un mot clé dans l'arbre des mots
         * clés
         * 
         * @param n
         *            le noeud à modifier
         * @param arbreMC
         *            le nouvel arbre de mots clés à mettre à jour
         */
        public void modifierMotCleDansArbre(TreeNode n, Tree arbreMC) {

                getIModele().modifierMotCleDansArbre(n, arbreMC);
                filtres.getMotsClesFiltre().rafraichir(n, false);

        }

        /**
         * Appelle le médiateur pour qu'il déplace un mot clé et son sous arbre dans
         * l'arbre des mots clés
         * 
         * @param n
         *            le noeud à déplacer
         * @param arbreMC
         *            le nouvel arbre de mots clés à mettre à jour
         */
        public void deplacerMotCleDansArbre(TreeNode n, Tree arbreMC) {

                getIModele().deplacerMotCleDansArbre(n, arbreMC);
                filtres.getMotsClesFiltre().rafraichir(n, false);
        }

        /**
         * initialise les mots clés cochés par rapport aux images sélectionnées
         */
        public void initialiserMotsCleCoches() {

                obtenirMotsClesId(metadonneesIptcExif.getPanneauMotsCles(),
                                getGalerieImage().getIdSelectionnees()[0]);
        }

        /**
         * Appelle le modèle pour lui demander les données d'une page à afficher
         * 
         * @param pageCourante
         *            le numéro de page à affciher
         */
        public void changerNumeroPage(int pageCourante) {

                // on met le mesage d'attente
                masquerChargement();

                // on appelle le modèle
                getIModele().changerNumeroPage(pageCourante);

                // et met à jour les numéros de page dans les barre d'outils
                getGalerieImage().getToolBarVue().changerPageCourante(pageCourante);
                getListeImage().getToolBarVue().changerPageCourante(pageCourante);
        }

        /**
         * Appelle le modèle pour qu'il change la taille de page utilisée
         * 
         * @param nouvelleTaillePage
         *            la nouvelle taille de page
         */
        public void changerTaillePage(int nouvelleTaillePage) {
                // on met le message d'attente
                masquerChargement();

                // on appelle le modèle
                getIModele().changerTaillePage(nouvelleTaillePage);

                // et on met à jour la taille de page dans les barres d'outils
                getGalerieImage().getToolBarVue().selectionnerTaillePage(
                                nouvelleTaillePage);
                getListeImage().getToolBarVue().selectionnerTaillePage(
                                nouvelleTaillePage);
        }

        /**
         * Met à jour les barre d'outils avec des nouvelles valeurs
         * 
         * @param pageMax
         *            le nombre de pages
         * @param pageEncours
         *            la page en cours
         * @param taillePage
         *            la taille de page
         * @param nbElement
         *            le nombre d'élements par page
         */
        public void changerPageMaxEtCourante(int pageMax, int pageEncours,
                        int taillePage, int nbElement) {

                int[] pages = { pageMax, pageEncours, taillePage, nbElement };
                getGalerieImage().getToolBarVue().rafraichir(pages, false);
                getListeImage().getToolBarVue().rafraichir(pages, false);

        }

        /**
         * Recherche l'élement actuellement affiché et affiche son message de
         * chargement
         */
        public void masquerChargement() {
                
                if(GWT.isScript()) {
                        ExtElement masked = Ext.get(getIdVueSelectionnee());
        
                        if (masked != null && !masked.isMasked()) {
                                masked.mask("Chargement", true);
                        }
                }
        }

        /**
         * Recherche l'élement actuellement affiché et retire son message de
         * chargement si l'était affiché
         */
        public void demasquerChargement() {
                
                if(GWT.isScript()) {
                        ExtElement masked = Ext.get(getIdVueSelectionnee());
                        if (masked != null && masked.isMasked()) {
                                masked.unmask();
                        }
                }
        }

        public void afficherMenuId() {
                IdVue i = new IdVue(this);
                i.show();
        }

        /**
         * C'est dans cette fonction que doivent être renvoyé les valeurs des
         * filtres sous forme de tableau [nom, valeur]
         * 
         * @return Les noms et valeurs des filtres
         */
        public String[][] renvoyerFiltres() {
                String[][] valeursFiltres = filtres.renvoyerValeursAFiltrer();
                
                /*for (int i = 0; i < valeursFiltres.length; i++) {
                        
                        if(valeursFiltres[i].equals(null))
                        {
                                Window.alert("Le filtre "+i+" est nul") ;
                        }
                        else
                        {
                                if(valeursFiltres[i][0].equals(null))
                                {
                                        Window.alert("Le nom du filtre "+i+" est nul") ;
                                }
                                
                                if(valeursFiltres[i][1].equals(null))
                                {
                                        Window.alert("La valeur du filtre "+i+" est nulle") ;
                                }
                        }
                }*/

                return valeursFiltres;
        }

        /**
         * Indique si les filtres ont changés depuis la dernière requête (il faut
         * faire un OR sur le résultat de toutes les fonctions renvoyerEtatFiltre
         * s'il y a plus d'un filtre)
         * 
         * @return true si au moins un des filtres a changé, false sinon
         */
        public boolean getEtatFiltres() {
                return (filtres.renvoyerEtatFiltre());
        }

        /**
         * Accesseur pour le panneau de droite contenant les filtres
         * 
         * @return le panneau contenant les filtres
         */
        public PanneauFiltresImagesVues getPanneauFiltres() {
                return filtres;
        }

        /**
         * ajoute les images séléctionnées dans la vue courante au tampon
         */
        public void ajouterImagesSelection() {
                String[] ids = getVueSelectionnee().getIdSelectionnees();
                String id = "";
                for (int i = 0; i < ids.length; i++) {
                        id += " - " + ids[i];
                }
                getIModele().ajouterImagesSelection(ids);

                Window.alert(ids.length + " image(s) ajoutées au tampon ");

        }
        
        /**
         * Affiche les ids des images contenues dans le tampon
         */
        public void afficherIdSelectionImages() {

                Window.alert("Contenu du tampon : " + getIModele().renvoyerSelection());

        }
        
        /**
         * Renvoie les ids des images contenues dans le tampon en une seule string
         * @return une string de la forme id1, id2, id3
         */
        public String renvoyerSelection() {
                return getIModele().renvoyerSelection();
        }
        
        /**
         * Vide le tampon d'images
         */
        public void viderSelection() {

                getIModele().viderSelection();
                Window.alert("Le tampon a été vidé ");

        }
        
        public int getCompteSelection() {
                return getIModele().getCompteSelection();
        }

        /**
         * Fonction appelée lors du drag 'n drop d'une image sur une observation
         * @param source la source du drag
         * @param e l'objet sur lequel on a fait le drop
         * @param data les données
         * @return une booleen indiquant le succès ou l'échec de l'opération
         */
        public boolean lierImagesDD(DragSource source, EventObject e, DragData data) {
                
                // on peut convertir directement les données car on a testé avant le type de données
                GridDragData gdd = (GridDragData)data ;
                // les ids des images sont initialisées 
                String idsImg = "" ;
                
                // on obtient la liste des selections dans la source
                Record[] aLier =  gdd.getSelections() ;
                for (int i = 0; i < aLier.length; i++) 
                {
                        // on les concatènes en une seule chaine       
                        idsImg += aLier[i].getAsString("id_image")+"," ;
                }
                
                MiniListeObservationVue mv = getMetadonneesIptcExif().getMiniListeObservation() ;
                // on cherche quel est la ligne sur laquelle on a fait le drop dans la la liste des observations
                int index = mv.getView().findRowIndex(e) ;
                Record rddrop = mv.getStore().getRecordAt(index) ;
                
                // SI l'enregistrement existe bel et bien
                if(rddrop != null)
                {
                        String idObs = rddrop.getAsString("id_obs")+"," ;
                        // on lie les observations
                        lierImagesObservation(idObs, idsImg) ;
                }
                
                return true ;     
        }
        
        /**
         * Fonction appelée lors du drag 'n drop d'une observation sur une image
         * @param source la source du drag
         * @param e l'objet sur lequel on a fait le drop
         * @param data les données
         * @return une booleen indiquant le succès ou l'échec de l'opération
         */
        public boolean lierObsDD(DragSource source, EventObject e, DragData data, String idDest) {
                
                // on peut convertir directement les données car on a testé avant le type de données
                GridDragData gdd = (GridDragData)data ;
                // les ids des images sont initialisées 
                String idsObs = "" ;
                
                // on obtient la liste des selections dans la source
                Record[] aLier =  gdd.getSelections() ;
                for (int i = 0; i < aLier.length; i++) 
                {
                        // on les concatènes en une seule chaine               
                        idsObs += aLier[i].getAsString("id_obs")+"," ;
                }
                
                Record rddrop = null ;
                
                // si la destination est la galerie d'images
                if(idDest.equals(getGalerieImage().getId()))
                {
                        GalerieImageVue gv = getGalerieImage() ;
                        
                        // alors l'élément sur lequel on a fait le drop n'est pas le bon
                        int index = gv.getDView().indexOf(e.getTarget()) ;
                        Element el = e.getTarget() ;
                        
                        // alors on cherche son parent tant que celui-ci n'est pas présent dans la dataview
                        while(index == -1 && el != null)
                        {
                                index = gv.getDView().indexOf(el) ;
                                el = (Element) el.getParentElement() ;
                        }
                        
                        // si on l'a trouvé, on obtient l'enregistrement qui correspond
                        if(index != -1)
                        {
                                rddrop = gv.getSt().getAt(index) ;
                        }
                                
                }
                
                // si la destination est la liste d'images
                if(idDest.equals(getListeImage().getId()))
                {
                        // on obtient directement l'enregistrement correspondant à l'élément sur lequel on a fait le drop
                        ListeImageVue lv = getListeImage() ;
                        int index = lv.getView().findRowIndex(e) ;
                        rddrop = lv.getSt().getAt(index) ;
                }
                
                // si on a bien obtenu un enregistrement 
                if(rddrop != null)
                {
                        // on récupère l'id de l'image et alors on appelle la fonction de liaison
                        String idImg = rddrop.getAsString("id_image")+"," ;
                        lierImagesObservation(idsObs, idImg) ;
                        
                        return true ;
                }
        
                
                // si la destination est l'image zoomée
                if(idDest.equals(getZoomImage().getId()))
                {
                        // on obtient directement l'id correspondant
                        ZoomImageVue zv = getZoomImage() ;
                        String idImg = zv.getIdImage() ;
                        lierImagesObservation(idsObs, idImg) ;
                        
                        return true ;                   
                }
                
                return false ;
                  
        }
        
        public void LierTamponObservations() {
                
                Record[] obsRec = getMetadonneesIptcExif().getMiniListeObservation().getSelectionModel().getSelections() ;
                String idsObs = "" ;
                
                for(int i =0 ; i< obsRec.length ; i++)
                {
                        idsObs += obsRec[i].getAsString("id_obs")+"," ;
                }
                
                if(getIModele().renvoyerSelection().equals("-255"))
                {
                        Window.alert("Le tampon est vide") ;
                        return ;
                }
                
                if(obsRec.length == 0)
                {
                        Window.alert("Aucune(s) observation(s) selectionnée(s)") ;
                        return ;
                }
                
                else
                {
                        lierImagesObservation(idsObs, getIModele().renvoyerSelection()) ;
                }
                
        }
        
        /**
         * Lie une ou plusieurs images à une ou plusieurs observations
         * @param idsObs les identifiants des observations séparés par des ","
         * @param idsImg les identifiants des images séparés par des ","
         */
        public void lierImagesObservation(String idsObs, String idsImg)
        {
                getIModele().lierImagesObervations(idsObs,idsImg) ;
        }

        public void deconnecterUtilisateur() {
                
                if(panneauPrincipalImage.isVisible())
                {
                        setIdentifiant(cMediateur.getUtilisateur().getIdentifiant()) ;
                        changerUtilisateur() ;
                }
                else
                {
                        panneauPrincipalImage.addListener(new ContainerListenerAdapter()
                        {
                                public void onRender(Component component)
                                {
                                        setIdentifiant(cMediateur.getUtilisateur().getIdentifiant()) ;
                                        changerUtilisateur() ;
                                        panneauPrincipalImage.purgeListeners() ;
                                }
                                
                        }) ;
                }
                
        }
        
        
        public void connecterUtilisateur() {
                
                if(panneauPrincipalImage.isVisible()) {
                        
                        setIdentifiant(cMediateur.getUtilisateur().getIdentifiant());
                        getIModele().initialiserArbreMotsCles();
                        obtenirPhotoGalerie(getGalerieImage());
                }       
                else
                {
                        if(this.iModele != null) {
                                panneauPrincipalImage.addListener(new ContainerListenerAdapter()
                                {
                                        public void onShow(Component c)
                                        {
                                                setIdentifiant(cMediateur.getUtilisateur().getIdentifiant());
                                                getIModele().initialiserArbreMotsCles();
                                                obtenirPhotoGalerie(getGalerieImage());
                                                panneauPrincipalImage.purgeListeners() ;
                                        }
                                        
                                }) ;
                        }
                        else
                        {
                                panneauPrincipalImage.addListener(new ContainerListenerAdapter()
                                {
                                        public void onRender(Component c)
                                        {
                                                setIdentifiant(cMediateur.getUtilisateur().getIdentifiant());
                                                getIModele().initialiserArbreMotsCles();
                                                obtenirPhotoGalerie(getGalerieImage());
                                                panneauPrincipalImage.purgeListeners() ;
                                        }
                                        
                                }) ;
                        }
                }
        }

        public void obtenirMiniListeObservations(
                        Rafraichissable r) {
                
                cMediateur.obtenirListeObservations(r) ;
                
        }

        public void afficherAide() {
                
                String aideUrl = Configuration.getAideBaseUrl() ;
                Window.open(aideUrl, "", "") ;
        }

        public void soumettreBugRemarque() {
        
                String suiviUrl = Configuration.getSuiviBugUrl() ;
                Window.open(suiviUrl, "", "") ;
                
        }

        public void obtenirObservationsAssociees() {
        
                String ids[] = getVueSelectionnee().getIdSelectionnees() ;
                getIModele().obtenirLiaisonObservations(this,ids[0]) ;
        }
        
        public void rafraichirMiniListeObservations(ListeObservation listeObs) {
                
                if(getMetadonneesIptcExif() != null && getMetadonneesIptcExif().isCreated()) {
                        if(getMetadonneesIptcExif().getMiniListeObservation().isCreated())
                        {
                                getMetadonneesIptcExif().getMiniListeObservation().rafraichir(listeObs, false) ;
                        }
                }
        }

        public void supprimerLiaisonObsImage() {
                
                String idImg = getVueSelectionnee().getIdSelectionnees()[0] ;
                String idObs = getMetadonneesIptcExif().getMiniListeObservation().getIdSelectionnees() ;
                
                if(Window.confirm("Supprimer le lien entre image(s) et observation(s) ?"))
                {
                        getMetadonneesIptcExif().getMiniListeObservation().supprimerLiaison() ;
                        iModele.supprimerLiaisonImages(idImg,idObs) ;
                }
                
        }
        
        public boolean estInstancie() {
                return estInstancie ;
        }

        public void donneesExterieures(Object o) {
                
                if(estInitialise) { 
                        iModele.rafraichir(o, true);
                }
        }

}