Rev 5 | Go to most recent revision | 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.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 = "" ;/*** 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)*/@SuppressWarnings("unused")private ArbreMotsClesVue(){super() ;}/*** Constructeur avec paramètre* @param im le médiateur à associer*/public ArbreMotsClesVue(ImageMediateur im){// on crée le panelsuper("Mots clés") ;this.setLayout(new VerticalLayout());iMediateur = im ;// on crée le conteneur de l'arbrearbreMotsCles = new TreePanel() ;// on permet le drag and drop dans l'arbrearbreMotsCles.setEnableDD(true) ;arbreMotsCles.setId("x-view-tree-keyword") ;// on crée une racine pour l'arbreTreeNode root = new TreeNode("Tags") ;root.setId("racine") ;String[] usObject = {"Mots clés" , "racine" } ;root.setUserObject(usObject) ;arbreMotsCles.setRootNode(root) ;arbreMotsCles.setRootVisible(false) ;arbreMotsCles.setBorder(false) ;arbreMotsCles.setWidth(500) ;// on crée l'éditeur pour l'arbretfEdit = new TextField() ;tfEdit.setAutoWidth(true) ;te = new TreeEditor(arbreMotsCles,tfEdit) ;valider = new Button("Appliquer") ;arbreMotsCles.add(te) ;// on met en forme le layoutthis.add(arbreMotsCles) ;this.add(valider) ;this.setBorder(false) ;this.setCollapsible(true) ;this.setTitleCollapse(true) ;// on ajoute les listenersajouterListeners() ;}/*** 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 noeudpublic void onClick(TreeNode node, EventObject e) {e.stopEvent() ;gererClicNoeud(node);}// gestion du clic droit sur un noeudpublic void onContextMenu(TreeNode node, EventObject e) {e.stopEvent() ;GetIMediateur().montrerContextMenuArbre(node, e , getTe()) ;}// gestion du double clic sur un noeudpublic void onDblClick(TreeNode node, EventObject e) {modifNoeud = true ;if(! node.getId().equals("racine")){te.startEdit(node);}}// gestion de la modification du texte d'un noeudpublic void onTextChange(TreeNode node, String text, String oldText) {// on récupère les informations associées au noeudTreeNode nd = node ;String[] usObject = new String[2] ;usObject[0] = text ;usObject[1] = ((String[])nd.getUserObject())[1] ;nd.setUserObject(usObject) ;// si c'est un nouveau noeudif(ajoutNoeud){// on notifie le médiateur de l'ajout et on lui passe l'arbreGetIMediateur().ajouterMotCleDansArbre(nd,getArbreMotsCles().getTree()) ;// et considière l'ajout achevéajoutNoeud = false ;}// si c'est noeud déjà existantelse{if(modifNoeud){// on notifie le médiateur de la modification et on lui passe l'arbreGetIMediateur().modifierMotCleDansArbre(nd,getArbreMotsCles().getTree()) ;// et on considère la modification achevéemodifNoeud = false ;}}}// gestion du déplacement d'un noeudpublic void onMoveNode(Tree tree, TreeNode node, TreeNode oldParent, TreeNode newParent,int index){// on notifie le médiateur et on lui passe l'arbreGetIMediateur().deplacerMotCleDansArbre(node, getArbreMotsCles().getTree()) ;}}) ;// gestion de la validationvalider.addListener(new ButtonListenerAdapter() {// lors du clicpublic void onClick(Button button, EventObject e) {// on vide les mots clés en coursmotsClesEnCours = "" ;// pour chaque noeud à partir de la racinegetArbreMotsCles().getRootNode().cascade(new NodeTraversalCallback() {// on éxécute une fonctionpublic boolean execute(Node node) {// on récupère le mot clé associé au noeud et ses infosTreeNode 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 coursmotsClesEnCours += usObject[1]+"," ;}return true ;}});// enfin on notifie le médiateur et on lui passe l'arbre et la liste des mots clés ainsi obtenueGetIMediateur().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étruitn.getParentNode().removeChild(n);n.destroy() ;// puis on en notifie le médiateur en lui passant le noeud supprimé et l'arbreGetIMediateur().supprimerMotCleDansArbre(n, arbreMotsCles.getTree()) ;}else{// si l'utilisateur tente de supprimer la racine, on l'avertit de son erreurWindow.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 à vraiajoutNoeud = true ;// on crée un nouveau noeud videTreeNode nd = new TreeNode("");nd.setCls("x-view-treenode-keyword") ;nd.setChecked(true);// on associe un objet au noeud qui contient des infosString[] usObject = new String[2] ;// l'objet contient le nom du noeudusObject[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 enfantsparent.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 racinegetArbreMotsCles().getRootNode().cascade(new NodeTraversalCallback() {// pour chaque noeudpublic boolean execute(Node node) {// on parcourt le tableau des mots clésfor(int i = 0 ; i < motsClesIds.length ; i++){// si le mot clé fait partie des id à cocher on le cocheString 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 suivantreturn 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 arbreif(nouvelleDonnees instanceof Tree){Tree nouvelArbre = (Tree)nouvelleDonnees ;if(nouvelArbre.getRootNode().getChildNodes().length <= 0){// on crée une racine pour l'arbreTreeNode root = new TreeNode("Tags") ;root.setId("racine") ;String[] usObject = {"Mots clés" , "racine" } ;root.setUserObject(usObject) ;}// on prend sa racine et on l'attache à l'arbre des mots clésNode[] rootChild = getArbreMotsCles().getRootNode().getChildNodes() ;for (int i = 0; i < rootChild.length; i++) {rootChild[i].remove() ;}getArbreMotsCles().getRootNode().appendChild(nouvelArbre.getRootNode()) ;// si l'arbre n'était pas encore considéré comme instanciéif(!estInstancie){// on signale que ouiestInstancie = 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 tableauString[] motsClesIds = (String[])nouvelleDonnees ;cocherMotsCles(motsClesIds) ;}// si l'arbre n'est pas encore instancié on met les mots clés en attenteelse{motsClesEnAttente = (String[])nouvelleDonnees ;}}}private String genererIdMotCle(TreeNode nd){return ""+(nd.hashCode()+(Math.random()*10000)) ;}}