Subversion Repositories eFlore/Archives.cel-v2

Rev

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

package org.tela_botanica.client.vues;


import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.interfaces.Rafraichissable;

import com.google.gwt.user.client.Window;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.data.Node;
import com.gwtext.client.data.NodeTraversalCallback;
import com.gwtext.client.data.Tree;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.form.TextField;
import com.gwtext.client.widgets.layout.RowLayout;
import com.gwtext.client.widgets.layout.RowLayoutData;
import com.gwtext.client.widgets.tree.TreeEditor;
import com.gwtext.client.widgets.tree.TreeNode;
import com.gwtext.client.widgets.tree.TreePanel;
import com.gwtext.client.widgets.tree.event.TreePanelListenerAdapter;

/**
 * Arbre des mots clés, qui est une vue rafraichissable,
 * qui contient des mots clés cochables et réorganisables à volonté
 * @author aurelien
 *
 */
public class ArbreMotsClesVue extends Panel implements Rafraichissable {

        /**
         * Le médiateur associé à la vue
         */
        private ImageMediateur iMediateur = null ;
        
        /**
         * Le treepanel qui affiche l'arbre
         */
        private TreePanel arbreMotsCles = null ;
        /**
         * L'éditeur qui permet de modifier les mots clés dans l'arbre
         */
        private TreeEditor te = null ;
        /**
         * Le textfield associé à l'éditeur
         */
        private TextField tfEdit = null ;
        /**
         * Bouton de validation
         */
        private Button valider = null ;
        /**
         * Une string permettant connaitre les mots clés cochés en cours séparés par des virgules
         */
        private String motsClesEnCours = "" ;
        /**
         * Tableau contenant les mots clés qui n'ont pas encore été jaouté à l'arbre 
         * (sert au lazy rendering quand on reçoit des mots clés avant que le rendu du conteneur n'ai été effectué)
         */
        private String[] motsClesEnAttente ; 
        /**
         * Booléen d'évènement qui sert à savoir si on est en train d'ajouter un noeud
         */
        private boolean ajoutNoeud = false ;
        /**
         * Booléen d'évènement qui sert à savoir si on est en train de modifier un noeud
         */
        private boolean modifNoeud = false ;
        /**
         * Booléen d'instanciation du conteneur
         */
        private boolean estInstancie = false ;
        /**
         * Booléen d'évènement qui sert à savoir si les mots clés ont bien été reçu
         */
        private boolean motsCleInitialises ;
        
        /**
         * Constructeur sans paramètre (privé car interdit d'utilisation)
         */
        private ArbreMotsClesVue()
        {
                super() ;
        }
        
        /**
         * Constructeur avec paramètre
         * @param im le médiateur à associer
         */
        public ArbreMotsClesVue(ImageMediateur im)
        {
                // on crée le panel
                super("Mots clés") ;
                this.setLayout(new RowLayout());
                iMediateur = im ;
                
                // on crée le conteneur de l'arbre
                arbreMotsCles = new TreePanel() ;
                // on permet le drag and drop dans l'arbre
                arbreMotsCles.setEnableDD(true) ;
                arbreMotsCles.setId("x-view-tree-keyword") ;
                arbreMotsCles.setAutoWidth(true) ;
                //arbreMotsCles.setAutoScroll(true) ;
                arbreMotsCles.setBorder(false) ;
                
                // on crée une racine pour l'arbre
                TreeNode root = new TreeNode("Tags") ;
                root.setId("racine") ;
                String[] usObject = {"Mots clés" , "racine" } ;
                root.setUserObject(usObject) ;
                
                arbreMotsCles.setAutoScroll(true) ;
                
                arbreMotsCles.setRootNode(root) ;
                arbreMotsCles.setRootVisible(false) ;
                arbreMotsCles.getRootNode().setIcon("tela.png") ;
                arbreMotsCles.setBorder(false) ;
                
                // on crée l'éditeur pour l'arbre
                tfEdit = new TextField() ;
                te = new TreeEditor(arbreMotsCles,tfEdit) ;
                valider = new Button("Appliquer") ;
                arbreMotsCles.add(te) ;
                
                // on met en forme le layout
                this.add(arbreMotsCles,new RowLayoutData("90%")) ;
                this.add(valider,new RowLayoutData("10%")) ;
                
                this.setBorder(false) ;
                this.setCollapsible(true) ;
                this.setTitleCollapse(true) ;
                
                // on ajoute les listeners
                ajouterListeners() ;
                
        }
        
        /**
         * Acesseur pour le médiateur
         * @return le médiateur associé à la vue
         */
        private ImageMediateur GetIMediateur() {
                
                return iMediateur ;
                
        }
        
        /**
         * Acesseur pour l'arbre des mots clés
         * @return le panel contenant l'arbre
         */
        public TreePanel getArbreMotsCles() {
                return arbreMotsCles;
        }

        /**
         * Accesseur pour l'éditeur
         * @return l'éditeur associé à l'arbre
         */
        public TreeEditor getTe() {
                return te;
        }

        /**
         * Acesseur pour le TextField associé à l'éditeur
         * @return le champ texte associé à l'éditeur
         */
        public TextField getTfEdit() {
                return tfEdit;
        }
        
        /**
         * Ajoute les listeners nécessaires pour la gestion des évènements
         */
        private void ajouterListeners()
        {
                arbreMotsCles.addListener(new TreePanelListenerAdapter() {
                        
                        // gestion du clic sur un noeud
                        public void onClick(TreeNode node, EventObject e) {
                                
                                e.stopEvent() ;
                                gererClicNoeud(node);
                        }

                        // gestion du clic droit sur un noeud
                        public void onContextMenu(TreeNode node, EventObject e) {
                                
                                        e.stopEvent() ;
                                        GetIMediateur().montrerContextMenuArbre(node, e , getTe()) ;
                                
                        }
                
                        // gestion du double clic sur un noeud
                        public void onDblClick(TreeNode node, EventObject e) {
                                
                                modifNoeud = true ;
                                te.startEdit(node);
                        }
                        
                        // gestion de la modification du texte d'un noeud 
                        public void onTextChange(TreeNode node, String text, String oldText) {

                                // on récupère les informations associées au noeud
                                TreeNode nd = node ;
                                String[] usObject = new String[2] ;
                                usObject[0] = text ;
                                usObject[1] = ((String[])nd.getUserObject())[1] ;
                                nd.setUserObject(usObject) ;
                                
                                // si c'est un nouveau noeud
                                if(ajoutNoeud)
                                {
                                        // on notifie le médiateur de l'ajout et on lui passe l'arbre
                                        GetIMediateur().ajouterMotCleDansArbre(nd,getArbreMotsCles().getTree()) ;
                                        // et considière l'ajout achevé
                                        ajoutNoeud = false ;
                                }
                                // si c'est noeud déjà existant
                                else
                                {
                                        // on notifie le médiateur de la modification et on lui passe l'arbre
                                        GetIMediateur().modifierMotCleDansArbre(nd,getArbreMotsCles().getTree()) ;
                                        // et on considère la modification achevée
                                        modifNoeud = false ;
                                }
                                
                        }
                        
                        // gestion du déplacement d'un noeud
                        public void onMoveNode(Tree tree, TreeNode node, TreeNode oldParent, TreeNode newParent,int index)
                        {
                                // on notifie le médiateur et on lui passe l'arbre
                                GetIMediateur().deplacerMotCleDansArbre(node, getArbreMotsCles().getTree()) ;
                        } 
                        
                }) ;
                
                // gestion de la validation
                valider.addListener(new ButtonListenerAdapter() {
                        
                        // lors du clic
                        public void onClick(Button button, EventObject e) {
                                
                                // on vide les mots clés en cours
                                motsClesEnCours = "" ;
                                // pour chaque noeud à partir de la racine
                                getArbreMotsCles().getRootNode().cascade(new NodeTraversalCallback() {
                                        
                                        // on éxécute une fonction
                                        public boolean execute(Node node) {
                                        
                                                        // on récupère le mot clé associé au noeud et ses infos
                                                        TreeNode tn = getArbreMotsCles().getNodeById(node.getId()) ;

                                                                String[] usObject =  (String[])tn.getUserObject() ;
                                                                GetIMediateur().mettreAjourMotsClesId(usObject[0],usObject[1]) ;
                                                                        
                                                                        if(tn.getUI().isChecked())
                                                                        {
                                                                                // et les concatène à la string des mots clés en cours
                                                                                motsClesEnCours += usObject[1]+"," ;
                                                                        }
                                                        
                                                        return true ;
                                        }
                                        
                                });
                                
                                // enfin on notifie le médiateur et on lui passe l'arbre et la liste des mots clés ainsi obtenue
                                GetIMediateur().mettreAjourMotsCles(motsClesEnCours,arbreMotsCles.getTree()) ;
                        }
                }) ;
                
        }
        
        /**
         * Envoie une demande au médiateur pour obtenir l'arbre des mots clés
         */
        public void obtenirArbreMotsCles() {
                
                GetIMediateur().obtenirArbreMotsCles(this) ;
                
        }

        /**
         * Supprime un noeud de l'arbre
         * @param n le noeud à supprimer
         */
        public void supprimerNoeud(TreeNode n)
        {
                // si ça n'est pas la racine (qu'on ne peut pas supprimer)
                if(!n.getId().equals(getArbreMotsCles().getRootNode().getId()))
                {
                        // on détache le noeud et on le détruit
                        n.getParentNode().removeChild(n);
                        n.destroy() ;
                        // puis on en notifie le médiateur en lui passant le noeud supprimé et l'arbre
                        GetIMediateur().supprimerMotCleDansArbre(n, arbreMotsCles.getTree()) ;
                }
                else
                {
                        // si l'utilisateur tente de supprimer la racine, on l'avertit de son erreur
                        Window.alert("Impossible de supprimer la racine de l'arbre") ;
                }
        }
        
        /**
         * Ajoute un noeud dans l'arbre au parent donné
         * @param parent le futur parent du noeud à ajouter
         */
        public void ajouterNoeud(TreeNode parent)
        {
                
                        // on met l'ajout du noeud à vrai
                        ajoutNoeud = true ;
                        // on crée un nouveau noeud vide
                        TreeNode nd = new TreeNode("");
                        nd.setIcon("tela.png") ;
                        nd.setChecked(true);
                        // on associe un objet au noeud qui contient des infos
                        String[] usObject = new String[2] ;
                        // l'objet contient le nom du noeud
                        usObject[0] = "" ;
                        usObject[1] = Integer.toString(nd.hashCode()) ;
                        nd.setId(usObject[1]) ;
                        nd.setUserObject(usObject) ;
                        // l'identifiant d'un noeud c'est son hashcode
                        // l'objet associé au noeud contient aussi son identifiant
                        
                        // on le concatène au parent et on étend ses enfants
                        parent.appendChild(nd);
                        parent.expand();
                        // enfin on place le curseur et on fait apparaitre le champ d'édition pour que l'utilisateur nomme son mot clé
                        te.startEdit(nd);

                
        }
        
        /**
         * Coche le noeud s'il est décoché, le décoche sinon
         * @param node
         */
        public void gererClicNoeud(TreeNode node)
        {
                if(node.getUI().isChecked())
                {
                        node.getUI().toggleCheck(false) ;
                }
                else
                {
                        node.getUI().toggleCheck(true) ;
                }
        }
        
        /**
         * Parcourt l'arbre et coche les noeud qui font partie de la liste des mots clés à cocher 
         * @param motsClesIds un tableau contenant les identifiants des mots clés à cocher
         */
        public void cocherMotsCles(final String[] motsClesIds)
        {
                if(getArbreMotsCles() != null && getArbreMotsCles().getRootNode() != null)
                {
                        // à partir de la racine
                        getArbreMotsCles().getRootNode().cascade(new NodeTraversalCallback() {
        
                                // pour chaque noeud
                                public boolean execute(Node node) {
                                        
                                                // on parcourt le tableau des mots clés
                                                for(int i = 0 ; i < motsClesIds.length ; i++)
                                                {
                                                        // si le mot clé fait partie des id à cocher on le coche
                                                        String usObject[] = (String[])node.getUserObject() ;
                                                        String nodeId = usObject[1] ;
                                                                                
                                                        if(nodeId.equals(motsClesIds[i]))
                                                        {
                                                                getArbreMotsCles().getNodeById(nodeId).getUI().toggleCheck(true) ;
                                                                return true ;
                                                        }
                                                        
                                                        getArbreMotsCles().getNodeById(node.getId()).getUI().toggleCheck(false) ;
                                                }
                                                // et on passe au suivant
                                                return true;
                                }
                                
                        }) ;
                }
        }
        
        /**
         * Méthode héritée de l'interface rafraichissable
         * @param nouvelleDonnees les nouvelles données pour l'objet
         * @param repandreRafraichissement booleen qui dit si on doit répandre l'évenement
         */
        public void rafraichir(Object nouvelleDonnees,
                        boolean repandreRafraichissement) {
                
                // si on a reçu un arbre
                if(nouvelleDonnees instanceof Tree)
                {
                                Tree nouvelArbre = (Tree)nouvelleDonnees ;
                                        
                                        // on prend sa racine et on l'attache à l'arbre des mots clés
                                Node[] rootChild = getArbreMotsCles().getRootNode().getChildNodes() ;
                                        for (int i = 0; i < rootChild.length; i++) {
                                                
                                                rootChild[i].remove() ;
                                        }
                                        getArbreMotsCles().getRootNode().appendChild(nouvelArbre.getRootNode()) ;
                                        getArbreMotsCles().expandAll() ;
                                        
                                        // si l'arbre n'était pas encore considéré comme instancié
                                        if(!estInstancie)
                                        {
                                                // on signale que oui
                                                estInstancie = true ;
                                        }
                                        
                                        // s'il y a des mots clés en attente (lors du premier rendering)
                                        if(motsCleInitialises == false && motsClesEnAttente != null)
                                        {
                                                // on les coche
                                                cocherMotsCles(motsClesEnAttente) ;
                                                motsCleInitialises = true ; 
                                        }
                }
                
                
                // Si on reçoit un tableau de String (cas ou l'on séléectionne une nouvelle image)
                if(nouvelleDonnees instanceof String[])
                {
                        // et que l'arbre est instancié
                        if(estInstancie && nouvelleDonnees != null)
                        {
                                // le tableau de String contient les id des mots clés associés à l'image
                                // on coche les mots clés contenu dans le tableau
                                String[] motsClesIds = (String[])nouvelleDonnees ;              
                                cocherMotsCles(motsClesIds) ;           
                        }
                        // si l'arbre n'est pas encore instancié on met les mots clés en attente
                        else
                        {
                                motsClesEnAttente = (String[])nouvelleDonnees ;
                        }
                }
                
        }

}