Rev 2227 | Blame | Compare with Previous | Last modification | View Log | RSS feed
package org.tela_botanica.client.vues.image;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.dd.DragData;import com.gwtext.client.dd.DragDrop;import com.gwtext.client.widgets.Button;import com.gwtext.client.widgets.Component;import com.gwtext.client.widgets.Container;import com.gwtext.client.widgets.Panel;import com.gwtext.client.widgets.Toolbar;import com.gwtext.client.widgets.ToolbarButton;import com.gwtext.client.widgets.event.ButtonListenerAdapter;import com.gwtext.client.widgets.event.WindowListenerAdapter;import com.gwtext.client.widgets.form.TextField;import com.gwtext.client.widgets.layout.FitLayout;import com.gwtext.client.widgets.layout.HorizontalLayout;import com.gwtext.client.widgets.layout.RowLayout;import com.gwtext.client.widgets.layout.RowLayoutData;import com.gwtext.client.widgets.tree.MultiSelectionModel;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;/*** Arbre des mots clés, qui est une vue rafraichissable, qui contient des mots* clés cochables et réorganisables à volonté** @author aurelien**/public abstract class FenetreGestionMotsCles extends com.gwtext.client.widgets.Window implements Rafraichissable {/*** 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;/*** Bouton d'annulation*/private Button annuler = null;/*** Bouton d'ajout de tag*/private ToolbarButton ajouterTag = null;/*** Bouton de suppression de tag*/private ToolbarButton supprimerTag = null;/*** Bouton de renommage de tag*/private ToolbarButton renommerTag = 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;/*** panneau intermédiaire contenant l'arbre*/private Panel panelIntermediaire;private String cheminTemporaireAjout;/*** Constructeur avec paramètre** @param im* le médiateur à associer*/public FenetreGestionMotsCles() {// on crée le panelsetTitle("Mots clés");this.setLayoutData(new RowLayout());// 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-imgs");arbreMotsCles.setSelectionModel(new MultiSelectionModel());// on crée une racine pour l'arbreTreeNode root = new TreeNode("Tags");root.setId("racine");String[] usObject = { "Mots clés", "racine" };root.setExpandable(true);arbreMotsCles.setRootNode(root);arbreMotsCles.setRootVisible(true);arbreMotsCles.setBorder(false);arbreMotsCles.setWidth(500);root.setUserObject(usObject);arbreMotsCles.getRootNode().addListener(new TreeNodeListenerAdapter() {@Overridepublic void onClick(Node node, EventObject e) {if(!arbreCharge) {expand();}}@Overridepublic void onExpand(Node node) {if(!arbreCharge) {obtenirArbreMotsCles();arbreCharge = true;}}});// on crée l'éditeur pour l'arbretfEdit = new TextField();tfEdit.setAutoWidth(true);te = new TreeEditor(arbreMotsCles, tfEdit);valider = new Button("Appliquer");annuler = new Button("Annuler");arbreMotsCles.add(te);panelIntermediaire = new Panel();panelIntermediaire.setLayout(new FitLayout());panelIntermediaire.setAutoScroll(true);panelIntermediaire.setWidth("100%");arbreMotsCles.setWidth("100%");arbreMotsCles.setHeight("100%");Panel panelBoutons = new Panel();panelBoutons.setLayout(new HorizontalLayout(130));panelBoutons.setWidth("100%");// on met en forme le layoutpanelIntermediaire.add(arbreMotsCles);panelBoutons.add(annuler);panelBoutons.add(valider);this.add(panelIntermediaire, new RowLayoutData());this.add(panelBoutons, new RowLayoutData(30));arbreMotsCles.setHeight("100%");arbreMotsCles.setAutoScroll(true);Toolbar barreBouton = new Toolbar();ajouterTag = new ToolbarButton("Nouveau Tag");ajouterTag.setIcon("mot_cle_ajouter.png");renommerTag = new ToolbarButton("Renommer");renommerTag.setIcon("mot_cle_editer.png");renommerTag.disable();supprimerTag = new ToolbarButton("Supprimer");supprimerTag.setIcon("mot_cle_supprimer.png");supprimerTag.disable();barreBouton.addButton(ajouterTag);barreBouton.addSeparator();barreBouton.addButton(renommerTag);barreBouton.addSeparator();barreBouton.addButton(supprimerTag);this.setTopToolbar(barreBouton);setCloseAction(com.gwtext.client.widgets.Window.HIDE);// on ajoute les listenersajouterListeners();}/*** 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;}protected abstract void surAffichageMenuContextuel(TreeNode node, EventObject e, TreeEditor te);protected abstract void surAjoutMotCle(TreeNode node, Tree arbre);protected abstract void surSuppressionMotCle(TreeNode node, Tree arbre);protected abstract void surDeplacementMotCle(TreeNode node, Tree arbre);protected abstract void surChangementTexte(TreeNode node, Tree arbre);protected abstract void surClicValider(String chaineMotsCles, Tree arbre);protected abstract void demanderArbreMotsCles(Rafraichissable r);protected abstract void surRetourWebService(Tree arbre);/*** Ajoute les listeners nécessaires pour la gestion des évènements*/private void ajouterListeners() {this.addListener(new WindowListenerAdapter() {@Overridepublic void onResize(com.gwtext.client.widgets.Window source, int width,int height) {panelIntermediaire.setHeight(getHeight() - 80);}});arbreMotsCles.addListener(new TreePanelListenerAdapter() {@Overridepublic void onAfterLayout(Container self) {panelIntermediaire.setHeight(getHeight() - 80);}@Overridepublic void onExpandNode(TreeNode node) {cocherMotsCles(tableauMotsClesEnCours);}// gestion du clic sur un noeud@Overridepublic void onClick(TreeNode node, EventObject e) {e.stopEvent();gererClicNoeud(node);if(!node.equals(arbreMotsCles.getRootNode())) {supprimerTag.enable();renommerTag.enable();}}// gestion du clic droit sur un noeud@Overridepublic void onContextMenu(TreeNode node, EventObject e) {e.stopEvent();surAffichageMenuContextuel(node, e, getTe());if(!node.equals(arbreMotsCles.getRootNode())) {supprimerTag.enable();renommerTag.enable();}}// gestion de la modification du texte d'un noeud@Overridepublic void onTextChange(TreeNode node, String text, String oldText) {if(!MotsClesUtilitaire.estUnMotCleAutorise(text)) {te.startEdit(node);Window.alert("Un mot clé ne peut pas être vide ou contenir les caractères suivants : "+MotsClesUtilitaire.getChaineCaracteresInterdits());return;}if(!MotsClesUtilitaire.estUnePositionAutorisee(node, node.getParentNode(), text)) {te.startEdit(node);Window.alert("Un mot clé de même nom existe déjà à cette position");return;}if(node.equals(arbreMotsCles.getRootNode())) {return;}// 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 considère l'ajout achevéajoutNoeud = false;// et on notifie le médiateur de l'ajout et on lui passe// l'arbresurAjoutMotCle(nd, getArbreMotsCles().getTree());arbreMotsCles.disable();}// si c'est noeud déjà existantelse {// on considère la modification achevéemodifNoeud = false;if(!text.equals(oldText)) {// et on notifie le médiateur de la modification et on lui// passe l'arbresurChangementTexte(nd, getArbreMotsCles().getTree());arbreMotsCles.disable();}}}@Overridepublic boolean doBeforeMoveNode(Tree tree, TreeNode node,TreeNode oldParent, TreeNode newParent, int index) {boolean ok = true;if(!MotsClesUtilitaire.estUnePositionAutorisee(node, newParent, node.getText())) {ok = false;Window.alert("Un mot clé de même nom existe déjà à cette position");}return ok;}@Overridepublic boolean onNodeDragOver(TreePanel treePanel, TreeNode target,DragData dragData, String point, DragDrop source,TreeNode dropNode) {return MotsClesUtilitaire.estUnePositionAutorisee(dropNode, target, dropNode.getText());}// gestion du déplacement d'un noeud@Overridepublic void onMoveNode(Tree tree, TreeNode node,TreeNode oldParent, TreeNode newParent, int index) {// on notifie le médiateur et on lui passe l'arbresurDeplacementMotCle(node, getArbreMotsCles().getTree());}});// gestion de la validationvalider.addListener(new ButtonListenerAdapter() {// lors du clic@Overridepublic 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 fonction@Overridepublic 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 obtenuesurClicValider(motsClesEnCours, arbreMotsCles.getTree());}});annuler.addListener(new ButtonListenerAdapter() {@Overridepublic void onClick(Button button, EventObject e) {hide();}});renommerTag.addListener(new ButtonListenerAdapter() {@Overridepublic void onClick(Button button, EventObject e) {TreeNode[] noeuds = ((MultiSelectionModel)arbreMotsCles.getSelectionModel()).getSelectedNodes();TreeNode noeudRenommage;if(noeuds.length > 0) {noeudRenommage = noeuds[noeuds.length - 1];} else {noeudRenommage = arbreMotsCles.getRootNode();}renommerNoeud(noeudRenommage);}});ajouterTag.addListener(new ButtonListenerAdapter() {@Overridepublic 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);}});supprimerTag.addListener(new ButtonListenerAdapter() {@Overridepublic void onClick(Button button, EventObject e) {TreeNode[] noeuds = ((MultiSelectionModel)arbreMotsCles.getSelectionModel()).getSelectedNodes();for (int i = 0; i < noeuds.length; i++) {supprimerNoeud(noeuds[i]);}}});}/*** Envoie une demande au médiateur pour obtenir l'arbre des mots clés*/public void obtenirArbreMotsCles() {demanderArbreMotsCles(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("Êtes vous sur de vouloir supprimer le mot clé "+n.getText()+" ?")) {// 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'arbresurSuppressionMotCle(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) {ajoutNoeud = true;TreeNode nd = MotsClesUtilitaire.ajouterNoeud(parent, true);// on le concatène au parent et on étend ses enfantsparent.appendChild(nd);parent.expand();cheminTemporaireAjout = nd.getId();te.startEdit(nd);}/*** Renomme le noeud passé en paramètre*/public void renommerNoeud(TreeNode n) {// TODO Auto-generated method stubte.startEdit(n);}/*** 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 noeud@Overridepublic boolean execute(Node node) {String usObject[] = (String[]) node.getUserObject();String nodeId = usObject[1];TreeNode tn = getArbreMotsCles().getNodeById(node.getId());if(tn != null) {tn.getUI().toggleCheck(false);// 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 cocheif (nodeId.equals(motsClesIds[i])) {tn.getUI().toggleCheck(true);tn.ensureVisible();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*/@Overridepublic 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ésNode[] 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 ouiarbreCharge = 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 tableautableauMotsClesEnCours = (String[]) nouvelleDonnees;if(this.isVisible()) {cocherMotsCles(tableauMotsClesEnCours);} else {addListener(new WindowListenerAdapter() {@Overridepublic void onShow(Component component) {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);cheminTemporaireAjout = null;}}surRetourWebService(arbreMotsCles.getTree());arbreMotsCles.enable();}/*** 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.setChecked(false);child.setUserObject(usObj);ndPereCopie.appendChild(child);if (!ndNodeFils[i].isLeaf()) {copierFilsNoeud(ndNodeFils[i], child);}}}}public void activerBoutonValider(boolean activer) {valider.setVisible(activer);}}