Subversion Repositories eFlore/Applications.cel

Rev

Rev 2615 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

package org.tela_botanica.client.vues.image;

import java.util.HashMap;
import java.util.Iterator;

import org.tela_botanica.client.i18n.Msg;
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.interfaces.ListePaginable;
import org.tela_botanica.client.interfaces.Rafraichissable;
import org.tela_botanica.client.modeles.objets.ListeObservation;
import org.tela_botanica.client.modeles.objets.Observation;
import org.tela_botanica.client.modeles.objets.Ontologies;
import org.tela_botanica.client.util.Util;
import org.tela_botanica.client.vues.MiniBarrePaginationVue;

import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.SimpleStore;
import com.gwtext.client.data.Store;
import com.gwtext.client.dd.DragSource;
import com.gwtext.client.dd.DropTarget;
import com.gwtext.client.dd.DropTargetConfig;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.Container;
import com.gwtext.client.widgets.Toolbar;
import com.gwtext.client.widgets.event.ContainerListenerAdapter;
import com.gwtext.client.widgets.form.ComboBox;
import com.gwtext.client.widgets.form.event.ComboBoxListenerAdapter;
import com.gwtext.client.widgets.grid.CellMetadata;
import com.gwtext.client.widgets.grid.ColumnConfig;
import com.gwtext.client.widgets.grid.ColumnModel;
import com.gwtext.client.widgets.grid.GridDragData;
import com.gwtext.client.widgets.grid.GridPanel;
import com.gwtext.client.widgets.grid.Renderer;
import com.gwtext.client.widgets.grid.RowSelectionModel;
import com.gwtext.client.widgets.grid.event.GridHeaderListenerAdapter;
import com.gwtext.client.widgets.grid.event.GridListenerAdapter;
import com.gwtext.client.widgets.grid.event.RowSelectionListenerAdapter;
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.core.EventObject;
import com.gwtext.client.core.Ext;
import com.gwtext.client.core.ExtElement;
import com.gwtext.client.core.SortDir;
import com.gwtext.client.dd.DragData;

/**
 * liste d'observation pour l'association d'images aux observations
 * @author aurelien
 *
 */
public class MiniListeObservationVue extends GridPanel implements Rafraichissable, ListePaginable {

        /**
         * Le médiateur associé à la vue
         */
        private ImageMediateur iMediateur = null ;
        
        /**
         * Booléen d'instanciation
         */
        private boolean estInstancie = false ;
        
        /**
         * Le modèle de colonnes
         */
        private ColumnModel colModel = null ;
        
        private SimpleStore store = null ;
        
        private MiniBarrePaginationVue pgBar = new MiniBarrePaginationVue(this) ;
        
        private Toolbar bt = new Toolbar() ;
        
        /**
         * Combobox permettant de selectionner le mode
         * modification ou bien création
         */
        private ComboBox selecteurMode = new ComboBox();
        
        Store storeMode = null ;

        private boolean liaison;
        
        int pageEnCours = 0;
        
        int nbElements = 0;
        
        int taillePage = 50;
        
        private String modeleLieu = "IDLOCLOCALITE, LIEUDIT, STATION";
        
        /**
         * Nombre de pages totales
         */
        private int pageMax = 1 ;
        
        private SortDir directionTri;

        private String champTri;
        
        private boolean triActif;
        
        /**
         * Constructeur avec arguments
         * @param im le médiateur à associer à la vue
         */
        public MiniListeObservationVue(ImageMediateur im)
        {
                iMediateur = im ;
                
                directionTri = SortDir.ASC;
                
                this.setId("x-view-mini-obs") ;
                
                // on construit le modèle de colonnes

                // Le store suivant est ensuite remplacé par le store contenant les données obtenus depuis le serveur (cf rafraichir)                                 
                Renderer colRend = new Renderer() {

                        @Override
                        public String render(Object value, CellMetadata cellMetadata,
                                        Record record, int rowIndex, int colNum, Store store) {
                                
                                if(value == null || value.equals("null") || value.equals("000null") || value.equals("0000-00-00 00:00:00")) {
                                
                                        return "" ;
                                }       
                                
                                return value.toString() ;
                        }
                        
                } ;
                
                Renderer dateRend = new Renderer() {

                        @Override
                        public String render(Object value, CellMetadata cellMetadata,
                                        Record record, int rowIndex, int colNum, Store store) {
                                
                                if(value == null || value.equals("null") || value.equals("000null") || value.equals("0000-00-00 00:00:00")) {
                                
                                        return "" ;
                                }       
                                else
                                {
                                        String dateEntiere = value.toString() ;
                                        String[] dateEtHeure = dateEntiere.split(" ", 2);
                                        if(verifierFormatDate(dateEtHeure[0])) {
                                                String[] dateFormateeTab = dateEtHeure[0].split("-",3);
                                                return dateFormateeTab[2]+"/"+dateFormateeTab[1]+"/"+dateFormateeTab[0] ;
                                        }
                                }
                                
                                return value.toString() ;
                        }
                        
                } ;
                
                // on crée un store simple contenant un petit set de données et deux colonnes
                store = new SimpleStore(new String[]{"transmis","nomSaisi_observation","date_observation","lieu_observation","ordre_observation","id_obs"}, getObs());  
                ColumnConfig[] columns = { 
                new ColumnConfig("", "transmis", 30, true, new Renderer() {

                        @Override
                        public String render(Object value, CellMetadata cellMetadata,
                                        Record record, int rowIndex, int colNum, Store store) {
                                if(value.equals("1"))
                                {
                                        return "<img src=\"tela.png\"/></img>" ;
                                }
                                else
                                {
                                        return "" ;
                                }
                        }
                        
                }),    
                new ColumnConfig(Msg.get("taxon"), "nomSaisi_observation", 145, true, colRend), 
                new ColumnConfig(Msg.get("date"), "date_observation", 68, true, dateRend),
                new ColumnConfig(Msg.get("lieu"), "lieu_observation", 145, true, colRend),              
                new ColumnConfig(Msg.get("numero"), "ordre_observation", 50, true, colRend), } ;
                   
                
        ColumnModel columnModel = new ColumnModel(columns);
         
        colModel = columnModel ;

         
        setTitle(Msg.get("observations"));  
        // on associe le modèle de colonnes
        setColumnModel(columnModel);  
        setAutoScroll(true) ;
        setHeight("100%") ;
                setAutoWidth(true) ; 
        // on autorise le drag 'n drop pour un certain groupe
                this.setEnableDragDrop(true);
                this.setDdGroup("DragGroupName");
        store.load();       
                setStore(store) ;
                
                setBottomToolbar(pgBar) ;
                Object[][] mode = {{Msg.get("toutes-observations"),false} , {Msg.get("observations-liees"), true} };
                storeMode = new SimpleStore(new String[] { "nom_mode", "mode" },
                                mode);
                storeMode.load();
                selecteurMode.setStore(storeMode);
                selecteurMode.setDisplayField("nom_mode") ;
                selecteurMode.setLabel("mode ") ;
                selecteurMode.setForceSelection(true) ;
                selecteurMode.setValue(Msg.get("toutes-observations")) ;
                selecteurMode.setEditable(false) ;
                selecteurMode.setCls("x-selec-consult") ;
                
                bt = new Toolbar() ;
                bt.addField(selecteurMode) ;
                
                //this.setAutoExpandColumn("plante");
                
                setTopToolbar(bt) ;
                
                this.addGridHeaderListener(new GridHeaderListenerAdapter() {            
                        @Override
                        public void onHeaderClick(GridPanel grid, int colIndex, EventObject e) {
                                triActif = true;
                                Timer t = new Timer() {
                                        
                                        @Override
                                        public void run() {
                                                enregistrerEtatTri();
                                                // Trier ne change pas le nombre de pages, on peut donc se passer d'un appel
                                                // au comptage (ce serait mieux si ces deux appels étaient combinés)
                                                obtenirMiniListeObservations();
                                        }
                                };
                                // Le changement de tri n'est pas immédiat et si on recharge le liste tout de suite 
                                // on a l'ancien tri et pas le nouveau (200 millisecondes suffisent et ne se voient pas)
                                // #mondeDeMerde
                                t.schedule(200);
                        }
                });
                
                selecteurMode.addListener(new ComboBoxListenerAdapter() {

                        @Override
                        public void onSelect(ComboBox comboBox, Record record, int index) {
                                
                                // et on met la valeur à jour dans la combobox
                                comboBox.setValue(record.getAsString("nom_mode"));
                                setModification(record.getAsString("mode")) ;
                        }

                });
                
                setAutoScroll(true) ;
                // on configure le drag 'n drop
                configDragAndDrop() ;
                
                
                this.addGridListener(new GridListenerAdapter() {

                        @Override
                        public void onContextMenu(EventObject e) {
                                
                                // si pas de selection, on selectionne au moins la ligne sur laquelle on a fait le clic
                                if(getSelectionModel().getSelections().length <= 0) {
                                        int index = getView().findRowIndex(e);
                                        Record rddrop = getStore().getRecordAt(index) ;
                                        getSelectionModel().selectRecords(rddrop);
                                }
                                
                                e.stopEvent() ;
                                MenuLiaisonVue mlv = new MenuLiaisonVue(iMediateur,liaison) ;
                                mlv.showAt(e.getXY()) ;
                                
                        }
                        
                }) ;
                
                // TODO: voir s'il existe un autre moyen de désactiver la multiselection
                // ça semble bien compliqué de faire comme ça
                getSelectionModel().addListener(new RowSelectionListenerAdapter() {             
                        @Override
                        public boolean doBeforeRowSelect(RowSelectionModel sm, int rowIndex,
                                        boolean keepExisting, Record record) {
                                sm.clearSelections();
                                return true;
                        }
                });
                
                obtenirNombreMiniListeObservations();
        }
        
        /**
         * Configure le drag 'n drop pour la liste
         */
        private void configDragAndDrop()
        {
                // on choisit le texte qui sera affiché lors d'un drag 'n drop
                setDragDropText(Msg.get("glissez-deposer-obs-images")) ;
                
                //On active le drag 'n drop
                this.setEnableDragDrop(true);

                // on fabrique la nouvelle configuration
                // les éléments sur lesquels on fait du drag 'n drop doivent tous avoir le même ddGroup
                this.setDdGroup("DragGroupName");
                DropTargetConfig dtc = new DropTargetConfig();
                dtc.setdDdGroup("DragGroupName");

                //La drop target permet de gérer l'évenement onDrop sur l'élement courant
                @SuppressWarnings("unused")
                DropTarget tg = new DropTarget(this, dtc)
                {
                        @Override
                        public boolean notifyDrop(DragSource source, EventObject e, DragData data){     
                                
                                // si on reçoit des données provenant d'une grille
                                if(data instanceof GridDragData)
                          {
                                        // on la convertit 
                                        GridDragData gdd = (GridDragData)data ;
                                        // et on vérifie que les données ne viennent pas de l'élément courant
                                        if(gdd.getGrid().getId().equals("x-view-mini-obs"))
                                        {
                                                return false ;
                                        }
                                        else
                                        {
                                                // on appelle le médiateur
                                                return iMediateur.lierImagesDD(source, e, data) ;   
                                        }
                          }
                                return false ;
                        }
                        
                        @Override
                        public String notifyOver(DragSource source, EventObject e, DragData data){
                            return "x-dd-drop-ok";
                        }
                };
        
        }
        
        /**
         * Méthode héritée de l'interface rafraichissable
         */
        @Override
        public void rafraichir(Object nouvelleDonnees,
                        boolean repandreRaffraichissement) {
                
                if(nouvelleDonnees instanceof ListeObservation)
                {
                        if(this.getView() != null)
                        {
                                ListeObservation data = (ListeObservation)nouvelleDonnees ;
                                String[][] listeObs = new String[data.size()][6] ;
                                int i = 0 ;
                                
                                for (Iterator it = data.keySet().iterator(); it.hasNext();) 
                                {
                                        
                                        Observation obs=data.get(it.next());
                                        
                                        listeObs[i][0] = obs.getTransmis();
                                        listeObs[i][1] = obs.getNomSaisi();
                                        listeObs[i][2] = obs.getDate() ;
                                        listeObs[i][3] = Util.formaterLieu(obs, modeleLieu);
                                        listeObs[i][4] = obs.getNumeroOrdre();
                                        listeObs[i][5] = obs.getId();
                                
                                        i++ ;
                                }
        
                                store = new SimpleStore(new String[]{"transmis","nomSaisi_observation","date_observation","lieu_observation","ordre_observation","id_obs"}, listeObs);  
                                store.sort(champTri, directionTri);
                                store.load();       
                                this.reconfigure(store, colModel) ;
                        }
                        else
                        {
                                addListener(new ContainerListenerAdapter() {
                                        
                                        @Override
                                        public void onShow(Component c)
                                        {
                                                obtenirNombreMiniListeObservations() ;
                                        }
                                        
                                        @Override
                                        public void onAfterLayout(Container c)
                                        {
                                                obtenirNombreMiniListeObservations() ;
                                        }
                                        
                                }) ;
                        }
        
                }
                
                // Si on reçoit un tableau d'entiers
                // c'est un tableau d'un seul entier qui est le nombre d'observation correspondant aux critères
                if(nouvelleDonnees instanceof int[])
                {
                        int[] pages = (int[])nouvelleDonnees ;
                        
                        // on calcule le nombre de pages nécessaires et on les met à jour dans le modèle
                        pageMax  = calculerNbPages(pages[0]) ;
                        nbElements = pages[0];          
                        
                        // et on notifie de le mediateur du changement des valeurs
                        changerPageMaxEtCourante(pageMax,pageEnCours,taillePage,nbElements) ;
                        
                        masquerChargement();
                        obtenirMiniListeObservations();
                }
                
                redimensionner();
                
                deMasquerChargement() ;
                
        }
        
        private void obtenirMiniListeObservations()
        {
                iMediateur.obtenirMiniListeObservations(this, taillePage, pageEnCours) ;
        }
        
        private void obtenirNombreMiniListeObservations()
        {
                iMediateur.obtenirNombreMiniListeObservations(this) ;
        }
        
        /**
         * Renvoie le faux set de données pour le store
         * @return un tableau à deux colonnes int - String
         */
        private Object[][] getObs() {  
                 return new Object[][]{  
                              
                 } ;
         }
        
        @Override
        public Store getStore()
        {
                return store ;
        }
        
        public MiniBarrePaginationVue getBarrePagination()
        {
                return pgBar ;
        }
        
        private void setModification(String mode)
        {
                if(mode.equals("true")) {

                        liaison = true ;
                        selecteurMode.removeClass("x-selec-consult") ;
                        selecteurMode.setCls("x-selec-liaison") ;
                        getBarrePagination().disable();
                        doLayout();
                }
                else
                {
                        liaison = false ;
                        selecteurMode.removeClass("x-selec-liaison") ;
                        selecteurMode.setCls("x-selec-consult") ;
                        getBarrePagination().enable();
                        doLayout();
                }
                
                store.removeAll() ;
                iMediateur.changerModeLiaison(liaison) ;
                
        }
        
        public boolean getMode() {
                return liaison ;
        }
        
        /**
         * Recherche l'élement actuellement affiché et affiche son message de chargement
         */
        public void masquerChargement()
        {
                        ExtElement masked = Ext.get(getId()) ;

                        if (masked!=null) {
                                masked.mask(Msg.get("chargement")) ;
                        }
        }
        
        /**
         * Recherche l'élement actuellement affiché et affiche son message de chargement
         */
        public void deMasquerChargement()
        {
                        ExtElement masked = Ext.get(getId()) ;

                        if (masked!=null) {
                                masked.unmask() ;
                        }
        }
        
        public String getIdSelectionnees() {
                
                Record[] sels = getSelectionModel().getSelections() ;
                
                String id = "";
                
                for(int i = 0; i < sels.length; i++) {
                        id += ","+sels[i].getAsString("id_obs") ;
                }
                
                id = id.replaceFirst(",", "");
                
                return id ;
                
        }
        
        public void supprimerLiaison() {
                
                
                Record[] rdObs = getSelectionModel().getSelections() ;
                
                for(int i = 0 ; i < rdObs.length ; i++) {
                        
                        getStore().remove(rdObs[i]) ;
                        this.getView().refresh() ;
                
                }
                
        }
        
        public void redimensionner() {
                if(getView() != null) {
                        
                        int taille = 400;
                        
                        if(Window.getClientHeight() > 800 ) {
                                taille = Window.getClientHeight() - 350;
                        }
                        setHeight(taille);
                        getView().setForceFit(true);
                        doLayout();
                }
                else {

                }
        }
        
        /**
         * Montre le menu de liaison aux coordonnées indiquées
         * @param e
         */
        public void montrerContextMenuLiaison(EventObject e) {
                
                final Menu liObs = new Menu();
                
                final Item lierObservation = new Item(Msg.get("lier-images-selectionnes"));
                liObs.addItem(lierObservation);
                
                liObs.addListener(new MenuListenerAdapter() {

                        // gestion du clic sur un item
                        @Override
                        public void onItemClick(BaseItem item, EventObject ev) {

                                // si c'est la suppression
                                if (item.equals(lierObservation)) {
                                        // on notifie le médiateur

                                }
                                
                                // enfin, on cache le menu
                                liObs.hide();

                        }

                });
                
                liObs.showAt(e.getXY());
        }

        @Override
        public void changerNumeroPage(int pageCourante) {
                
                pageEnCours = pageCourante ;    
                masquerChargement();

                // On lance le chargerment des observations
                iMediateur.obtenirNombreMiniListeObservations(this);
                
        }
        
        /**
         * Appelle le modèle pour qu'il change la taille de page utilisée
         * @param nouvelleTaillePage la nouvelle taille de page
         */
        
        @Override
        public void changerTaillePage(int nouvelleTaillePage)
        {
        
                taillePage = nouvelleTaillePage ;
                pageEnCours = calculerPageCourante(nbElements) ;

                masquerChargement();

                // On lance le chargerment des observations
                iMediateur.obtenirNombreMiniListeObservations(this);
                
                
                // et on met à jour la taille de page dans les barres d'outils
                pgBar.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} ;
                pgBar.rafraichir(pages, false) ;
                
        }
        
        /**
         * Calcule le nombre de pages nécessaires pour afficher un nombre d'élements donnés en fonction de la taille de page
         * en cours
         * @param nbElements le nombre d'élements total
         * @return le nombre de pages 
         */
        public int calculerNbPages(int nbElements)
        {
                // A cause de la betise de java pour les conversion implicite on fait quelques conversions manuellement
                // pour eviter qu'il arrondisse mal la division
                // nombre de pages = (nombre d'element / taille de la page) arrondie à l'entier superieur
                
                double nPage = (1.0*nbElements)/(1.0*taillePage) ; 
                double nPageRound = Math.ceil(nPage) ;
                Double nPageInt = new Double(nPageRound) ;
                
                // on convertit en entier
                return nPageInt.intValue() ; 
        }

        
        /**
         * Recalcule la page en cours lors du changement du nombre d'élements
         * @param nbElements le nombre d'élements total
         * @return la nouvelle page encours
         */
        public int calculerPageCourante(int nbElements)
        {
                // on calcule le nombre de page
                int nouvelNbPages = calculerNbPages(nbElements) ;
                // la nouvelle page en cours
                double nPageCourante = (1.0*pageEnCours)/(1.0*pageMax) * (1.0*nouvelNbPages) ;
                
                // on arrondit au supérieur
                double nPageRound = Math.ceil(nPageCourante) ;
                Double nPageInt = new Double(nPageRound) ;
                
                // on convertit en entier
                return Math.abs(nPageInt.intValue()) ; 
        }
        
        public boolean verifierFormatDate(String date) {
                
                String regex = "[1-9][0-9]{3}-[0-9]{2}-[0-9]{2}" ;
                if(date.matches(regex) && !date.equals("0000-00-00")) {
                        return true ;
                }
                else {
                        return false;
                }
        }
        
        private void enregistrerEtatTri() {
                if(triActif) {
                        this.directionTri = store.getSortState().getDirection();
                        this.champTri = store.getSortState().getField();
                }
                
        }

        public String renvoyerTri() {
                String tri = "ordre";
                if(triActif) {
                        HashMap<String, String> corr = Ontologies.getCorrespondanceGrilleObservationChampsTri();
                        if(corr.containsKey(champTri)) {
                                tri = corr.get(champTri);
                        }
                }
                return tri;
        }

        public String renvoyerDirectionTri() {
                String triDir = "ASC";
                try {
                        triDir = (triActif) ? directionTri.getDirection() : "ASC";
                } catch (Exception e) {
                        triDir = "ASC";
                }
                return triDir;
        }
}