New file |
0,0 → 1,500 |
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 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(false); |
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() { |
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; |
if (!node.getId().equals("racine")) { |
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 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 |
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.setCls("x-view-treenode-keyword"); |
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] = 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); |
|
} |
|
/** |
* 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) { |
|
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 |
*/ |
public void rafraichir(Object nouvelleDonnees, |
boolean repandreRafraichissement) { |
// si on a reçu un arbre |
if (nouvelleDonnees instanceof Tree) { |
Tree nouvelArbre = (Tree) nouvelleDonnees; |
|
if (nouvelArbre.getRootNode().getChildNodes().length <= 0) { |
// 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); |
} |
|
// 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().getRootNode().cascade(new NodeTraversalCallback() { |
|
public boolean execute(Node node) { |
|
String usObject[] = (String[]) node |
.getUserObject(); |
String nodeId = usObject[1]; |
|
getArbreMotsCles().getNodeById(nodeId) |
.getUI().toggleCheck(false); |
|
return false; |
} |
|
|
}) ; |
|
// 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) { |
// 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; |
} |
} |
} |
|
private String genererIdMotCle(TreeNode nd) { |
return "" + (nd.hashCode() + (Math.random() * 10000)); |
} |
|
} |