Subversion Repositories eFlore/Applications.cel

Rev

Rev 2042 | Blame | 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 org.tela_botanica.client.util.MotsClesUtilitaire;

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.VerticalLayout;
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 = "";
        
        private String[] tableauMotsClesEnCours = new String[0];
        /**
         * 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 d'évènement qui sert à savoir si les mots clés ont bien été reçu
         */
        private boolean motsCleInitialises;

        private String cheminTemporaireAjout;

        /**
         * Constructeur sans paramètre (privé car interdit d'utilisation)
         */
        @SuppressWarnings("unused")
        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 VerticalLayout());
                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");

                // 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.setRootNode(root);
                arbreMotsCles.setRootVisible(true);
                arbreMotsCles.setBorder(false);
                arbreMotsCles.setWidth(500);

                // on crée l'éditeur pour l'arbre
                tfEdit = new TextField();
                tfEdit.setAutoWidth(true);
                te = new TreeEditor(arbreMotsCles, tfEdit);
                valider = new Button("Appliquer");
                arbreMotsCles.add(te);

                // on met en forme le layout
                this.add(arbreMotsCles);
                this.add(valider);

                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() {
                
                final Rafraichissable r = this;
                arbreMotsCles.addListener(new TreePanelListenerAdapter() {

                        @Override
                        public void onExpandNode(TreeNode node) {               
                                cocherMotsCles(tableauMotsClesEnCours);
                        }
                        
                        // gestion du clic sur un noeud
                        @Override
                        public void onClick(TreeNode node, EventObject e) {
                                e.stopEvent();
                                gererClicNoeud(node);
                        }

                        // gestion du clic droit sur un noeud
                        @Override
                        public void onContextMenu(TreeNode node, EventObject e) {
                                e.stopEvent();
                                getIMediateur().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")) {
                                        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 considère l'ajout achevé
                                        ajoutNoeud = false;
                                        // et on notifie le médiateur de l'ajout et on lui passe
                                        // l'arbre
                                        getIMediateur().ajouterMotCleDansArbre(nd,
                                                        getArbreMotsCles().getTree(), ArbreMotsClesVue.this);
                                }
                                // si c'est noeud déjà existant
                                else {
                                        // et on considère la modification achevée
                                        modifNoeud = false;
                                        // on notifie le médiateur de la modification et on lui
                                        // passe l'arbre
                                        getIMediateur().modifierMotCleDansArbre(nd,
                                                        getArbreMotsCles().getTree(), ArbreMotsClesVue.this);
                                }

                        }

                        // 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
                                getIMediateur().deplacerMotCleDansArbre(node,
                                                getArbreMotsCles().getTree(), ArbreMotsClesVue.this);
                        }

                });

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

                        // lors du clic
                        @Override
                        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
                                                        @Override
                                                        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(), ArbreMotsClesVue.this);
                } 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) {
                ajoutNoeud = true;              
                TreeNode nd = MotsClesUtilitaire.ajouterNoeud(parent, false);
                // on le concatène au parent et on étend ses enfants
                parent.appendChild(nd);
                parent.expand();
                cheminTemporaireAjout = nd.getId();
                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
                                                @Override
                                                public boolean execute(Node node) {

                                                        getArbreMotsCles().getNodeById(node.getId())
                                                        .getUI().toggleCheck(false);
                                                        
                                                        // 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;
                                                                }
                                                        }
                                                        // 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
         */
        @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();
                        }
                        
                        MotsClesUtilitaire.copierFilsNoeud(nouvelArbre.getRootNode(),getArbreMotsCles().getRootNode(), true);

                        // si l'arbre n'était pas encore considéré comme instancié
                        if (!arbreCharge) {
                                // on signale que oui
                                arbreCharge = true;
                        }
                }

                // Si on reçoit un tableau de String (cas ou l'on séléectionne une
                // nouvelle image)
                if (nouvelleDonnees instanceof String[]) {

                                // 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
                                tableauMotsClesEnCours = (String[]) nouvelleDonnees;
                                cocherMotsCles(tableauMotsClesEnCours);
                }
                
                // reception d'un nouvel identifiant de mot clé
                if(nouvelleDonnees instanceof Integer) {
                        if(cheminTemporaireAjout != null) {
                                String id = ((Integer)(nouvelleDonnees)).toString();
                                TreeNode noeudEnAjout = arbreMotsCles.getNodeById(cheminTemporaireAjout);
                                String[] userObj = {noeudEnAjout.getText(), id};
                                noeudEnAjout.setUserObject(userObj);
                                noeudEnAjout.setId(id);
                                cheminTemporaireAjout = null;
                        }
                }
                
                arbreMotsCles.enable();
        }
}