Subversion Repositories eFlore/Applications.cel

Rev

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

package org.tela_botanica.client.vues.observation.filtres;
import org.tela_botanica.client.interfaces.Filtrable;
import org.tela_botanica.client.interfaces.Rafraichissable;
import org.tela_botanica.client.observation.ObservationMediateur;
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.dd.DragData;
import com.gwtext.client.dd.DragDrop;
import com.gwtext.client.dd.DropTargetConfig;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.event.PanelListenerAdapter;
import com.gwtext.client.widgets.form.TextField;
import com.gwtext.client.widgets.layout.VerticalLayout;
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.DropNodeCallback;
import com.gwtext.client.widgets.tree.MultiSelectionModel;
import com.gwtext.client.widgets.tree.TreeDragData;
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.TreeNodeListenerAdapter;
import com.gwtext.client.widgets.tree.event.TreePanelListenerAdapter;

public class ArbreMotsClesObservationVue extends Panel implements Rafraichissable, Filtrable {

                /**
                 * Le médiateur associé à la vue
                 */
                private ObservationMediateur oMediateur = null;

                /**
                 * Le treepanel qui affiche l'arbre
                 */
                private static 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 ajouterMotCle = 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 = new String[0];
                /**
                 * 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 arbreCharge = false;
                
                /**
                 * Booléen nécessaire pour l'affichage
                 * 
                 */
                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;
                
                private Component livue = null;
                
                MultiSelectionModel msModel = null;

                /**
                 * Constructeur sans paramètre (privé car interdit d'utilisation)
                 */
                @SuppressWarnings("unused")
                private ArbreMotsClesObservationVue() {
                        super();
                }

                /**
                 * Constructeur avec paramètre
                 * 
                 * @param im
                 *            le médiateur à associer
                 */
                public ArbreMotsClesObservationVue(ObservationMediateur om) {
                        // on crée le panel
                        super("Projets");
                        
                        this.setLayout(new VerticalLayout());
                        oMediateur = om;
                        
                        setBorder(false);
                        setCollapsible(true);
                        setTitleCollapse(true);
                        setAutoScroll(true);

                        // on ajoute les listeners
                        ajouterListenersPanel();

                }
                
                /**
                 * Ajoute les listeners pour le rendu du panel
                 */
                private void ajouterListenersPanel() {
                          this.addListener(new PanelListenerAdapter() {

                                // on instancie réellement les composants au moment du rendu pour
                                // accélérer l'affichage
                                // et éviter des bugs
                                @Override
                                public void onRender(Component component) {
                                        
                                        livue = oMediateur.getListeObservation();
                                        
                                        // 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-obs");
                                        
                                        
                                        msModel = new MultiSelectionModel();
                                        arbreMotsCles.setSelectionModel(msModel);

                                        // on crée une racine pour l'arbre
                                        TreeNode root = new TreeNode("Projets");
                                        root.setId("racine_obs");
                                        String[] usObject = { "Projets", "racine_obs" };
                                        root.setUserObject(usObject);
                                        root.setExpandable(true);
                                        
                                        arbreMotsCles.setRootNode(root);
                                        
                                        // on crée l'éditeur pour l'arbre
                                        tfEdit = new TextField();
                                        te = new TreeEditor(arbreMotsCles, tfEdit);
                                        ajouterMotCle = new Button("Ajouter un projet");
                                        arbreMotsCles.add(te);
                                        
                                        arbreMotsCles.getRootNode().addListener(new TreeNodeListenerAdapter() {
                                                @Override
                                                public void onClick(Node node, EventObject e) {
                                                        if(!arbreCharge) {
                                                                expand();
                                                        }
                                                }

                                                @Override
                                                public void onExpand(Node node) {
                                                        if(!arbreCharge) {
                                                                obtenirArbreMotsCles();
                                                                arbreCharge = true;
                                                        }
                                                }
                                        });

                                        // on interdit le drag and drop dans l'arbre
                                        arbreMotsCles.setRootVisible(true);
                                        arbreMotsCles.setBorder(false);
                                        
                                        // on met en forme le layout
                                        add(arbreMotsCles);
                                        add(ajouterMotCle);

                                        // enfin on considère le composant comme instancié
                                        estInstancie = true;
                                        
                                        configDragAndDrop();
                                        
                                        // on ajoute les listeners d'évenements
                                        ajouterListeners();                                     
                                }

                        });
                }

                /**
                 * Acesseur pour le médiateur
                 * 
                 * @return le médiateur associé à la vue
                 */
                private ObservationMediateur getOMediateur() {

                        return oMediateur;

                }

                /**
                 * 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
                                @Override
                                public void onClick(TreeNode node, EventObject e) {

                                        e.stopEvent();
                                        boolean multi = false;
                                        if(e.hasModifier()) {
                                                multi = true;
                                        }
                                        gererClicNoeud(node,multi);
                                }

                                // gestion du clic droit sur un noeud
                                @Override
                                public void onContextMenu(TreeNode node, EventObject e) {

                                        e.stopEvent();
                                        montrerContextMenuArbre(node, e, getTe());

                                }

                                // gestion du double clic sur un noeud
                                @Override
                                public void onDblClick(TreeNode node, EventObject e) {

                                        modifNoeud = true;
                                        if (!node.getId().equals("racine_obs")) {
                                                te.startEdit(node);
                                        }
                                }

                                // gestion de la modification du texte d'un noeud
                                @Override
                                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
                                                getOMediateur().ajouterMotCleDansArbre(nd,
                                                                getArbreMotsCles().getTree());
                                                // et considère l'ajout achevé
                                                ajoutNoeud = false;
                                        }
                                        // si c'est noeud déjà existant
                                        else {
                                                if (modifNoeud) {
                                                        // on notifie le médiateur de la modification et on lui
                                                        // passe l'arbre
                                                        getOMediateur().modifierMotCleDansArbre(nd,
                                                                        getArbreMotsCles().getTree());
                                                        // et on considère la modification achevée
                                                        modifNoeud = false;
                                                }
                                        }

                                }

                                // gestion du déplacement d'un noeud
                                @Override
                                public void onMoveNode(Tree tree, TreeNode node,
                                                TreeNode oldParent, TreeNode newParent, int index) {
                                        // on notifie le médiateur et on lui passe l'arbre
                                        getOMediateur().deplacerMotCleDansArbre(node,
                                                        getArbreMotsCles().getTree());
                                }
                                
                                @Override
                                public boolean doBeforeNodeDrop(TreePanel treePanel,
                                                TreeNode target, DragData dragData,
                                                String point, DragDrop source,
                                                TreeNode dropNode,
                                                DropNodeCallback dropNodeCallback) {
                                        
                                        if(dragData instanceof TreeDragData) {
                                                return true;
                                        }
                                                
                                        String idMotCle = ((String[])target.getUserObject())[1];
                                        
                                        if(oMediateur.gererDDObsSurMotCle(target, dragData)) {
                                                
                                                cocherMotCle(idMotCle);
                                                return true;
                                        }
                                        
                                        return false;
                                }


                                @Override
                                public void onNodeDrop(TreePanel treePanel,
                                                TreeNode target, DragData dragData,
                                                String point, DragDrop source, TreeNode dropNode) {

                                        
                                }

                        });

                        // gestion de la validation
                        ajouterMotCle.addListener(new ButtonListenerAdapter() {

                                // lors du clic
                                @Override
                                public void onClick(Button button, EventObject e) {
                                        
                                        TreeNode[] noeuds = ((MultiSelectionModel)arbreMotsCles.getSelectionModel()).getSelectedNodes();
                                        TreeNode noeudAjout;
                                        if(noeuds.length > 0) {
                                                noeudAjout = noeuds[noeuds.length - 1];
                                        } else {
                                                noeudAjout = arbreMotsCles.getRootNode();
                                        }

                                        ajouterNoeud(noeudAjout);
                                        
                                }
                        });

                }
                
                
                /**
                 * Configure le drag 'n drop pour la liste
                 */
                private void configDragAndDrop()
                {
                        // on fabrique la nouvelle configuration
                        // les éléments sur lesquels on fait du drag 'n drop doivent tous avoir le même ddGroup
                        arbreMotsCles.setDdGroup("ObsMotsClesGroup");
                        //arbreMotsCles.setEnableDD(true);
                        arbreMotsCles.setEnableDrag(true);
                        arbreMotsCles.setEnableDrop(true);
                        DropTargetConfig dtc = new DropTargetConfig();          
                        dtc.setdDdGroup("ObsMotsClesGroup"); 
                }

                /**
                 * Envoie une demande au médiateur pour obtenir l'arbre des mots clés
                 */
                public void obtenirArbreMotsCles() {

                        getOMediateur().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())) {
                                
                                if(Window.confirm("Etes vous sur de vouloir supprimer ce projet ?")) {
                                        // 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
                                        getOMediateur()
                                                        .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.setCls("x-view-treenode-keyword");
                        // 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] = genererIdMotCle(nd);
                        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);

                }

                /**
                 * Fonction de gestion sur le clic sur le noeud
                 * 
                 * @param node
                 */
                public void gererClicNoeud(TreeNode node, boolean multi) {
                        
                        if(!arbreCharge) {
                                obtenirArbreMotsCles();
                        } else {
                                if(multi) {
                                }
                                ((MultiSelectionModel)arbreMotsCles.getSelectionModel()).select(node, multi);
                                oMediateur.obtenirNombreObservation();
                        }
                }

                /**
                 * 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
                                                        @Override
                                                        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().getTextEl().addClassName("x-tree-node-text-kw");
                                                                                
                                                                                        return true;
                                                                        }
                                                                }
                                                                
                                                                if((getArbreMotsCles().getNodeById(node.getId()).getUI().getTextEl()) != null) {
                                                                        getArbreMotsCles().getNodeById(node.getId())
                                                                        .getUI().getTextEl().removeClassName("x-tree-node-text-kw");
                                                                }

                                                                
                                                                // et on passe au suivant
                                                                return true;
                                                        }

                                                });
                        }
                        else {
                                motsClesEnAttente = motsClesIds ;
                        }
                }
                
                public void cocherMotCle(String motCleId) {
                        getArbreMotsCles().getNodeById(motCleId)
                        .getUI().getTextEl().addClassName("x-tree-node-text-kw");
                }
                
                public void initialiser() {
                        
                        arbreCharge = false ;
                        motsClesEnCours = "";
                        arbreMotsCles.collapseAll();
                        // on vide l'ancien arbre
                        Node[] rootChild = arbreMotsCles.getRootNode().getChildNodes();
                        for (int i = 0; i < rootChild.length; i++) {
                                
                                rootChild[i].remove();
                        }
                        
                        arbreMotsCles.getRootNode().addListener(new TreeNodeListenerAdapter() {
                                
                                @Override
                                public void onExpand(Node node) {
                                        if(!arbreCharge)
                                        {
                                                obtenirArbreMotsCles() ;
                                                arbreCharge = 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
                 */
                @Override
                public void rafraichir(Object nouvelleDonnees,
                                boolean repandreRafraichissement) {
                        
                        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();
                                }
                                
                                copierFilsNoeud(nouvelArbre.getRootNode(),getArbreMotsCles().getRootNode());

                                // si l'arbre n'était pas encore considéré comme instancié
                                if (!arbreCharge) {
                                        // on signale que oui
                                        arbreCharge = 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;
                                }
                                
                                if(motsClesEnAttente.length > 0) {
                                        cocherMotsCles(motsClesEnAttente);
                                }
                        }

                        // Si on reçoit un tableau de String (cas ou l'on séléectionne une
                        // nouvelle obs)
                        if (nouvelleDonnees instanceof String) {
                                
                                String chaineMc = (String)nouvelleDonnees;
                                String[] motsClesIds = chaineMc.split(";");
                                
                                // et que l'arbre est instancié
                                if (arbreCharge) {
                                        // 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
                                        cocherMotsCles(motsClesIds);
                                        
                                }
                                // si l'arbre n'est pas encore instancié on met les mots clés en
                                // attente
                                else {
                                        motsClesEnAttente = motsClesIds;
                                }
                        }
                }

                private String genererIdMotCle(TreeNode nd) {
                        
                        double IdMC = (nd.hashCode() + ((Math.random() * 10000) + 1));                  
                        return ""+IdMC;
                }
                
                /**
                 * Fonction récursive qui prend deux noeuds d'arbre en paramètre et crée un
                 * copie du sous arbre du premier noeud, qu'elle concatène au deuxième
                 * 
                 * @param ndPereOriginal
                 *            le père des noeuds de l'arbre original
                 * @param ndPereCopie
                 *            le père qui va recevoir les copies
                 */
                private void copierFilsNoeud(Node ndPereOriginal, TreeNode ndPereCopie) {
                        if (ndPereCopie != null && ndPereOriginal != null) {
                                Node[] ndNodeFils = ndPereOriginal.getChildNodes();
                                
                                for (int i = 0; i < ndNodeFils.length; i++) {

                                        String[] usObj = (String[]) ndNodeFils[i].getUserObject();
                                        TreeNode child = new TreeNode(usObj[0]);
                                        child.setId(usObj[1]);
                                        child.setUserObject(usObj);
                                        ndPereCopie.appendChild(child);

                                        if (!ndNodeFils[i].isLeaf()) {
                                                copierFilsNoeud(ndNodeFils[i], child);
                                        }

                                }
                        }
                }
                
                public void raz() {
                        
                        arbreCharge = false ;
                        arbreMotsCles.collapseAll();
                        arbreMotsCles.clear() ;
                        
                        // on crée une racine pour l'arbre
                        TreeNode root = new TreeNode("Projets");
                        root.setId("racine_obs");
                        String[] usObject = { "Projets", "racine_obs" };
                        root.setUserObject(usObject);
                        root.setExpandable(true);

                        arbreMotsCles.setRootNode(root);
                        
                        arbreMotsCles.getRootNode().addListener(new TreeNodeListenerAdapter() {
                                
                                @Override
                                public void onExpand(Node node) {
                                        if(!arbreCharge)
                                        {
                                                obtenirArbreMotsCles() ;
                                                arbreCharge = true ;
                                        }
                                }
                                
                        }) ;
                        
                        motsClesEnCours  = "";
                }

                @Override
                public boolean renvoyerEtatFiltre() {
                        // TODO Auto-generated method stub
                        return false;
                }

                @Override
                public String renvoyerNomFiltre() {
                        // TODO Auto-generated method stub
                        return null;
                }

                @Override
                public String[] renvoyerValeursAFiltrer() {
                        
                        String val = "";
                        
                        TreeNode[] noeuds = ((MultiSelectionModel)arbreMotsCles.getSelectionModel()).getSelectedNodes();
                        
                        for(int i = 0; i< noeuds.length ; i++) {
                                if(noeuds[i].getDepth() > 0) {
                                        val += ";"+noeuds[i].getId();
                                }
                        }
                        
                        val = val.replaceFirst(";", "");
                        
                        String[] valeursFiltres = {"id_mots_cles", val};
                        
                        return valeursFiltres;
                }

                @Override
                public void valider() {
                        // TODO Auto-generated method stub
                        
                }
                

                public void montrerContextMenuArbre(final TreeNode n, EventObject e,
                                TreeEditor te) {
                                Menu mn = new Menu();
                                final com.gwtext.client.widgets.menu.Item ajoutN = new Item(
                                                "Ajouter un projet");
                                final com.gwtext.client.widgets.menu.Item suppN = new Item(
                                                "Supprimer projet");

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

                                mn.addListener(new MenuListenerAdapter() {

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

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

                @Override
                public void viderFiltre() {
                        arbreMotsCles.getSelectionModel().clearSelections();
                        motsClesEnCours = "";
                }
}