Subversion Repositories eFlore/Applications.cel

Compare Revisions

Ignore whitespace Rev 1 → Rev 2

/trunk/src/org/tela_botanica/client/vues/BarreNotationVue.java
New file
0,0 → 1,232
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.ui.ClickListener;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.MouseListenerAdapter;
import com.google.gwt.user.client.ui.Widget;
import com.gwtext.client.widgets.Panel;
 
/**
* Une barre de notation avec des étoiles, tout ce qu'il ya de plus classique,
* utilisant Ajax (et pas CSS)
* @author aurelien
*
*/
public class BarreNotationVue extends Panel implements Rafraichissable {
 
/**
* Le médiateur associé
*/
@SuppressWarnings("unused")
private ImageMediateur iMediateur = null ;
/**
* La note actuellement affichée
*/
private int noteEnCours = 0 ;
/**
* La note maximum
*/
private int noteMax = 0 ;
/**
* Booléen indiquant si une note est affectée à la barre en ce moment
*/
private boolean estNote = false ;
/**
* Tablmeau d'images contenant les étoiles affichées
*/
private Image[] etoiles = null ;
/**
* Constructeur sans argument (privé car ne doit pas être utilisé)
*/
@SuppressWarnings("unused")
private BarreNotationVue()
{
super() ;
}
/**
* Constructeur avec arguments
* @param im le médiateur à associer à la vue
* @param noteMax la note maximale
*/
public BarreNotationVue(ImageMediateur im, int noteMax)
{
iMediateur = im ;
setNoteMax(noteMax) ;
this.setSize(200, 100) ;
this.setBodyBorder(false) ;
this.setBorder(false) ;
this.setCls("x-view-notation") ;
ajouterListeners() ;
}
public void ajouterListeners()
{
for (int i = 0; i < etoiles.length; i++) {
etoiles[i].addMouseListener(new MouseListenerAdapter() {
 
 
// si la souris passe sur la barre
public void onMouseEnter(Widget sender) {
Image enCours = (Image)sender ;
// on met en surbrillance toutes les étoiles allant de la première jusqu'à
// celle sous le curseur
for(int i = 0 ; etoiles[i] != enCours ; i++)
{
etoiles[i].setUrl("note-hover.gif") ;
}
enCours.setUrl("note-hover.gif") ;
}
 
// si la souris sort de la barre
public void onMouseLeave(Widget sender) {
// on affiche la véritable note
afficherNote() ;
}
 
}) ;
etoiles[i].addClickListener(new ClickListener() {
// si on clique sur une étoiles
public void onClick(Widget sender) {
int i = 0 ;
// on récupère le numéro de l'étoile sur laquelle on a cliqué
while(etoiles[i] != (Image)sender)
{
i++ ;
}
// et on affecte la note
noter(i) ;
}
}) ;
}
}
/**
* Fonction héritée de l'interface rafraichissable
*/
public void rafraichir(Object nouvelleDonnees,
boolean repandreRaffraichissement) {
// si on recoit un tableau de string
if(nouvelleDonnees instanceof String[])
{
// on récupère le premier élément (un entier, qui contient la note)
String[] note = (String[])nouvelleDonnees ;
int noteInt = Integer.parseInt(note[0]) ;
// si l'entier est une note valide
if(noteInt != -1 && noteInt >= 0)
{
noter(noteInt) ;
}
// sinon si l'entier vaut -1
else
{
// alors on note avec 0
// et on met le booleen de notation a false (qui signifie que l'image n'est pas encore notée)
estNote = false ;
noteEnCours = 0 ;
// et demande l'affichage
afficherNote() ;
}
}
}
/**
* Affecte une note à la barre et rafraichit l'affichage
* @param note la nouvelle note
*/
public void noter(int note)
{
// on affecte la note
noteEnCours = note ;
// on met le boolean de notation à true (l'image est notée)
estNote = true ;
// et on demande l'affichage
afficherNote() ;
}
/**
* Setteur pour la note maximale
* @param nMax la nouvelle note maximale
*/
public void setNoteMax(int nMax)
{
// on affecte la note
noteMax = nMax ;
// on prépare le tableau d'image
etoiles = new Image[noteMax] ;
// qu'on remplit par defaut avec des images d'étoiles vides
for(int i = 0 ; i < noteMax ; i++)
{
etoiles[i] = new Image("etoile_vide.jpg") ;
etoiles[i].setStylePrimaryName("x-view-notation-bar") ;
this.add(etoiles[i]) ;
}
}
/**
* Affiche la note d'une image sous la forme d'étoiles
*/
public void afficherNote()
{
// si l'image est notée
if(estNote)
{
// on affiche autant d'étoiles que le chiffre de la note
for(int i = 0 ; i <= noteEnCours ; i++)
{
etoiles[i].setUrl("note-on.gif") ;
}
// et si elle est inférieure à la note maximale, on remplit le reste par des étoiles vides
for (int j = noteEnCours + 1 ; j < noteMax ; j++)
{
etoiles[j].setUrl("note-off.gif") ;
}
}
// sinon
else
{
// on remplit toute la barre avec des étoiles vides
for(int i = 0 ; i < noteMax ; i++)
{
etoiles[i].setUrl("note-off.gif") ;
}
}
}
/**
* Accesseur pour la note en cours sous forme de string
* @return
*/
public String getNote()
{
return ""+noteEnCours ;
}
 
}
/trunk/src/org/tela_botanica/client/vues/MenuImageVue.java
New file
0,0 → 1,103
package org.tela_botanica.client.vues;
 
import org.tela_botanica.client.image.ImageMediateur;
 
import com.gwtext.client.core.EventObject;
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;
 
/**
* Menu de gestion des images
* @author aurelien
*
*/
public class MenuImageVue extends Menu {
/**
* Le médiateur associé à la vue
*/
private ImageMediateur iMediateur ;
/**
* Item pour l'upload
*/
private Item uploaderImage = null ;
/**
* Item pour la suppression
*/
private Item supprimerImage = null ;
 
/**
* Constructeur sans argument (privé car ne doit être utilisé)
*/
@SuppressWarnings("unused")
private MenuImageVue()
{
super();
}
/**
* Constructeur avec paramètre
* @param im le médiateur à associer
*/
public MenuImageVue(ImageMediateur im)
{
super() ;
iMediateur = im ;
// on construit le menu
uploaderImage = new Item("Uploader des images") ;
supprimerImage = new Item("Supprimer les images selectionnées") ;
addItem(uploaderImage);
addItem(supprimerImage) ;
// on ajoute les listeners
ajouterListeners() ;
}
/**
* Ajoute les listeners pour la gestions des évènements
*/
private void ajouterListeners()
{
this.addListener(new MenuListenerAdapter() {
 
// gestion du clic sur un item
public void onItemClick(BaseItem item, EventObject e) {
// si c'est l'upload
if(item.equals(uploaderImage))
{
// on notifie le médiateur
getIMediateur().uploaderImages() ;
}
// si c'est la suppression
if(item.equals(supprimerImage))
{
// on notifie le médiateur
getIMediateur().supprimerImages() ;
}
// enfin, on cache le menu
hide() ;
}
}) ;
}
/**
* Accesseur pour le médiateur
* @return le médiateur associé à la vue
*/
public ImageMediateur getIMediateur()
{
return iMediateur ;
}
 
}
/trunk/src/org/tela_botanica/client/vues/ZoomImageVue.java
New file
0,0 → 1,387
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.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
import com.gwtext.client.core.RegionPosition;
import com.gwtext.client.widgets.Container;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.PanelListenerAdapter;
import com.gwtext.client.widgets.layout.BorderLayout;
import com.gwtext.client.widgets.layout.BorderLayoutData;
 
/**
* Panneau d'affichage d'une image avec des boutons précdents et suivant
* @author aurelien
*
*/
public class ZoomImageVue extends Panel implements Rafraichissable {
/**
* Le médiateur associé à la vue
*/
private ImageMediateur iMediateur = null ;
/**
* Panneau conteneur pour l'image
*/
private Panel imageConteneur = null ;
/**
* l'image à afficher
*/
private Image image = new Image("vide.jpg") ;
/**
* Bouton précédent
*/
private final com.google.gwt.user.client.ui.Button prev = new com.google.gwt.user.client.ui.Button();
/**
* Bouton suivant
*/
private final com.google.gwt.user.client.ui.Button suiv = new com.google.gwt.user.client.ui.Button();
/**
* Taille originale Y de l'image
*/
private int imageHeight = 0 ;
/**
* Taille originale X de l'image
*/
private int imageWidth = 0 ;
/**
* Booleen d'initalisation général
*/
private boolean initialise = false ;
/**
* Booleen d'initalisation du conteneur d'image
*/
private boolean conteneurInitialise = false ;
/**
* Constructeur sans argument (privé car ne doit être utilisé)
*/
@SuppressWarnings("unused")
private ZoomImageVue()
{
super() ;
}
/**
* Constructeur avec argument
* @param im le médiateur à associer à la vue
*/
public ZoomImageVue(ImageMediateur im)
{
super("Zoom");
setId("x-view-zoom-panel") ;
// on associe le médiateur
iMediateur = im ;
prev.setStylePrimaryName("x-view-zoom-button-p") ;
suiv.setStylePrimaryName("x-view-zoom-button-s") ;
 
// on crée une image qui gère le double clic et la roulette de la souris
image = new Image() {
public void onBrowserEvent(Event event) {
// lors du double clic
if (Event.ONDBLCLICK == DOM.eventGetType(event)) {
 
// on notifie le médiateur
getIMediateur().doubleClicZoomImage();
}
// lors d'un déplacement de la roulette
if (Event.ONMOUSEWHEEL == DOM.eventGetType(event)) {
 
// on simule un clic sur le bouton précédent
if(event.getMouseWheelVelocityY() >= 1)
{
prev.click() ;
}
// ou suivant
if(event.getMouseWheelVelocityY() <= -1)
{
suiv.click() ;
}
}
}
};
this.setHeader(false) ;
imageConteneur = new Panel() ;
imageConteneur.setBorder(false);
imageConteneur.add(image) ;
imageConteneur.setId("x-view-zoom-img") ;
// il n'existe pas de méthode pour ajouter un listener pour le double clic sur une image
// alors on lui dit manuellement de capter l'évènement double clic
image.sinkEvents(Event.ONDBLCLICK);
image.sinkEvents(Event.ONMOUSEWHEEL) ;
// l'image de base est vide
image.setUrl("vide.jpg");
this.setLayout(new BorderLayout());
prev.setWidth("60px");
suiv.setWidth("60px");
this.add(prev,new BorderLayoutData(RegionPosition.WEST));
this.add(imageConteneur,new BorderLayoutData(RegionPosition.CENTER));
this.add(suiv,new BorderLayoutData(RegionPosition.EAST));
imageConteneur.setMaskDisabled(true) ;
this.setBorder(false);
conteneurInitialise = true ;
initialise = true ;
// on ajoute les listeners
ajouterListeners();
 
}
 
/**
* Méthode héritée de l'interface rafraichissable
* @param nouvelleDonnees les nouvelles données
* @param repandreRafraichissement le booleen qui dit si on doit répnadre l'évènement
*/
public void rafraichir(Object nouvelleDonnees, boolean repandreRafraichissement) {
// si on reçoit une string
if(nouvelleDonnees instanceof String[] && initialise && conteneurInitialise)
{
String[] infos = (String[])nouvelleDonnees ;
// c'est l'url de l'image qu'on associe à la vue
getImage().setUrl(infos[0]);
if(infos[1] != null && infos[2] != null)
{
int x = Integer.parseInt(infos[1]) ;
int y = Integer.parseInt(infos[2]) ;
setTailleImage(x,y) ;
verifierEtRetaillerImage() ;
}
}
else
{
// sinon on met une image vide
getImage().setUrl("vide.jpeg") ;
}
}
/**
* Desactive visuellement le panneau et les boutons
*/
public void desactiverPanneau()
{
getImage().setUrl("vide.jpeg") ;
prev.setEnabled(false) ;
suiv.setEnabled(false);
}
/**
* Active visuellement le panneau et les boutons
*/
public void activerPanneau()
{
prev.setEnabled(true);
suiv.setEnabled(true);
}
/**
* Ajoute les listeners pour la gestions d'évènement
*/
public void ajouterListeners()
{
// gestion du clic sur le bouton précedent
prev.addClickListener(new ClickListener() {
 
// en cas de clic
public void onClick(Widget sender) {
// on notifie le médiateur
getIMediateur().clicBoutonZoomImage("prev");
}
});
// gestion du clic sur le bouton suivant
suiv.addClickListener(new ClickListener() {
 
// en cas de clic
public void onClick(Widget sender) {
// on notifie le médiateur
getIMediateur().clicBoutonZoomImage("suiv");
}
});
// gestion du redimensionnement
this.addListener(new PanelListenerAdapter() {
// lors d'un redimensionnement de l'application
public void onBodyResize(Panel panel,java.lang.String width,java.lang.String height)
{
// on vérifie et on retaille l'image
verifierEtRetaillerImage() ;
}
}) ;
// gestion du redimensionnement lors de l'affichage du conteneur
imageConteneur.addListener(new PanelListenerAdapter() {
// avant de finir d'afficher
public void onAfterLayout(Container self)
{
// on redimensionne
verifierEtRetaillerImage() ;
}
}) ;
}
 
/**
* Verifie si l'image est plus grande que le conteneur et la retaille le cas echeant
*/
public void verifierEtRetaillerImage()
{
// si l'image est nulle
if(image == null)
{
// on ne fait rien
return ;
}
// on prend la taille originale de l'image
int originalX = getTailleImage()[0] ;
int originalY = getTailleImage()[1] ;
// on la transforme en float (la division entre entier donne de curieux résultats)
float fOriginalX = (new Float(originalX)).floatValue() ;
float fOriginalY = (new Float(originalY)).floatValue() ;
// et on fait le rapport longueur sur hauteur (pour connaitre le ratio)
float rapportTaille = fOriginalX/fOriginalY ;
// la nouvelle taille est pour le moment égale à l'ancienne
int nouvelleTailleX = originalX ;
int nouvelleTailleY = originalY ;
// on prend la taille du conteneur
int tailleConteneurX = imageConteneur.getWidth() ;
int tailleConteneurY = imageConteneur.getHeight() ;
// si celle-ci est égale à 0 (conteneur mal initialisé)
/*if(imageConteneur.getHeight() == 0 && tailleConteneurX == 0)
{
// on essaie de la calculer en fonction de la taille du parent et des frères
tailleConteneurY = this.getHeight() ;
tailleConteneurX = this.getWidth() - prev.getOffsetWidth() * 2 ;
}*/
// si l'image ne rentre pas telle quelle (longueur ou hauteur trop grande)
if(originalY > tailleConteneurY || originalX > tailleConteneurX)
{
// si la longueur de l'image est la plus grande des deux
if(originalX > originalY)
{
// on prend la longueur comme taille de référence, qu'on met à la longueur du conteneur
nouvelleTailleX = tailleConteneurX ;
// et on recalcule la hauteur, par rapport à la nouvelle longueur, en gardant le format de 'limage
nouvelleTailleY = (int)Math.floor(nouvelleTailleX*1/rapportTaille) ;
}
else
{
// si la hauteur est la plus grande, on fait le même genre d'opération en prenant la hauteur comme référence
nouvelleTailleY = tailleConteneurY ;
nouvelleTailleX = (int)Math.floor(nouvelleTailleY*rapportTaille) ;
}
}
// on modifie enfin la taille de l'image pour qu'elle soit affichée
getImage().setSize(""+nouvelleTailleX+"px", ""+nouvelleTailleY+"px") ;
}
 
/**
* Accesseur pour le médiateur
* @return le médiateur associé à la vue
*/
public ImageMediateur getIMediateur() {
return iMediateur;
}
 
/**
* Accesseur au conteneur de l'image
* @return le conteneur de l'image
*/
public Image getImage() {
return image;
}
 
/**
* Accesseur pour le bouton précédent
* @return le bouton précédent
*/
public com.google.gwt.user.client.ui.Button getPrev() {
return prev;
}
 
/**
* Accesseur pour le bouton suivant
* @return le bouton suivant
*/
public com.google.gwt.user.client.ui.Button getSuiv() {
return suiv;
}
/**
* Setter pour la taille de l'image
* @param X la largeur en pixels
* @param Y la hauteur en pixels
*/
public void setTailleImage(int x, int y)
{
imageHeight = y ;
imageWidth = x ;
}
/**
* renvoie la taille originale de l'image
* @return un tableau de deux entiers contenant la largeur puis la hauteur
*/
public int[] getTailleImage()
{
int[] taille = {imageHeight,imageWidth} ;
return taille ;
}
 
public Panel getImageConteneur() {
return imageConteneur ;
}
}
/trunk/src/org/tela_botanica/client/vues/BarreRechercheFiltreVue.java
New file
0,0 → 1,158
package org.tela_botanica.client.vues;
 
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.interfaces.Filtrable;
import org.tela_botanica.client.interfaces.Rafraichissable;
 
import com.google.gwt.user.client.ui.Label;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.KeyListener;
import com.gwtext.client.widgets.form.TextField;
 
/**
* Fenêtre de recherche pour les mots clés, contenant un champ texte,
* et un bouton cliquable
* @author aurelien
*
*/
public class BarreRechercheFiltreVue extends Panel implements Rafraichissable, Filtrable {
 
/**
* Médiateur associé à la vue
*/
private ImageMediateur iMediateur = null ;
/**
* Barre de recherche
*
*/
private TextField champRecherche = null ;
/**
* Booleen d'etat du filtre
*/
private boolean filtreModifie = false ;
/**
* mot(s) à chercher
*/
private String motsAChercher = "" ;
/**
* Constructeur sans argument (privé car ne doit pas être utilisé)
*/
@SuppressWarnings("unused")
private BarreRechercheFiltreVue()
{
super() ;
}
/**
* Constructeur avec médiateur
* @param im
*/
public BarreRechercheFiltreVue(ImageMediateur im)
{
super() ;
iMediateur = im ;
Label labelRecherche = new Label("Commentaires :") ;
champRecherche = new TextField() ;
add(labelRecherche) ;
add(champRecherche) ;
setPaddings(5) ;
setBorder(false) ;
setAutoWidth(true) ;
setCollapsible(true) ;
ajouterListeners() ;
}
/**
* ajoute des listeners
*/
private void ajouterListeners()
{
// gestion de la touche entrée
champRecherche.addKeyListener(EventObject.ENTER, new KeyListener() {
 
public void onKey(int key, EventObject e) {
valider() ;
getIMediateur().obtenirPhotoGalerie(getIMediateur().getFiltreCommentaires()) ;
}
}) ;
}
/**
* Fonction héritée de l'interface rafraichissable
*/
public void rafraichir(Object nouvelleDonnees,
boolean repandreRaffraichissement) {
filtreModifie = false ;
}
 
/**
* renvoie l'état du filtre (modifié ou non)
* @return l'état du filtre
*/
public boolean renvoyerEtatFiltre() {
return filtreModifie ;
}
 
/**
* Renvoie le nom du filtre
* @return le nom du filtre
*/
public String renvoyerNomFiltre() {
return "Recherche Commentaires" ;
}
/**
* Renvoie un tableau contenant le nom du champ à filtrer et la valeur
* @return un tableau contenant le nom du champ à filtrer et sa valeur
*/
public String[] renvoyerValeursAFiltrer() {
String[] valeurFiltre = {"ci_meta_comment" , motsAChercher } ;
return valeurFiltre ;
}
/**
* Accesseur pour le médiateur
* @return le médiateur associé
*/
public ImageMediateur getIMediateur()
{
return iMediateur ;
}
/**
* Effectue quelque opérations dans la classe et envoie une requête de données
* au médiateur
*/
public void valider()
{
filtreModifie = true ;
motsAChercher = champRecherche.getText() ;
}
/**
* Affiche la fenetre
*/
public void afficherFiltre() {
champRecherche.setValue(motsAChercher) ;
}
 
}
/trunk/src/org/tela_botanica/client/vues/MenuFiltreVue.java
New file
0,0 → 1,99
package org.tela_botanica.client.vues;
 
import org.tela_botanica.client.image.ImageMediateur;
 
import com.gwtext.client.core.EventObject;
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;
 
public class MenuFiltreVue extends Menu {
 
/**
* Le médiateur associé à la vue
*/
private ImageMediateur iMediateur ;
/**
* Item pour la recherche par mots clés
*/
private Item chercherImage = null ;
/**
* Item pour la recherche sur les commentaires
*/
private Item chercherCommentaire = null ;
/**
* Constructeur sans argument (privé car ne doit être utilisé)
*/
@SuppressWarnings("unused")
private MenuFiltreVue()
{
super();
}
/**
* Constructeur avec paramètre
* @param im le médiateur à associer
*/
public MenuFiltreVue(ImageMediateur im)
{
super() ;
iMediateur = im ;
// on construit le menu
chercherImage = new Item("Filtrer par les mots clés") ;
chercherCommentaire = new Item("Filtrer par les commentaires") ;
addItem(chercherImage) ;
addItem(chercherCommentaire) ;
// on ajoute les listeners
ajouterListeners() ;
}
/**
* Ajoute les listeners pour la gestions des évènements
*/
private void ajouterListeners()
{
this.addListener(new MenuListenerAdapter() {
 
// gestion du clic sur un item
public void onItemClick(BaseItem item, EventObject e) {
// si c'est la recherche par mots clé
if(item.equals(chercherImage))
{
// on notifie le médiateur
// getIMediateur().afficherFiltreMotsCles() ;
}
// si c'est la recherche par commentaires
if(item.equals(chercherCommentaire))
{
// on notifie le médiateur
//getIMediateur().afficherFiltreCommentaires() ;
}
// enfin, on cache le menu
hide() ;
}
}) ;
}
/**
* Accesseur pour le médiateur
* @return le médiateur associé à la vue
*/
public ImageMediateur getIMediateur()
{
return iMediateur ;
}
}
/trunk/src/org/tela_botanica/client/vues/PanneauMetadonneesVue.java
New file
0,0 → 1,363
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.ui.Label;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.NameValuePair;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.TabPanel;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.form.DateField;
import com.gwtext.client.widgets.form.TextArea;
import com.gwtext.client.widgets.form.TextField;
import com.gwtext.client.widgets.grid.GridPanel;
import com.gwtext.client.widgets.grid.GridView;
import com.gwtext.client.widgets.grid.PropertyGridPanel;
import com.gwtext.client.widgets.grid.event.GridCellListenerAdapter;
import com.gwtext.client.widgets.layout.VerticalLayout;
 
/**
* Panneau contenant les infos, les métadonnées et l'arbre des mots clés, il implémente l'interface rafraichissable
* @author aurelien
*
*/
public class PanneauMetadonneesVue extends TabPanel implements Rafraichissable {
 
/**
* Le médiateur associé à la vue
*/
private ImageMediateur imediateur = null ;
/**
* Le panneau des Exifs
*/
private PropertyGridPanel ExifGrid = null ;
/**
* Le panneau des Iptc
*/
private PropertyGridPanel IptcGrid = null ;
/**
* La grille pour le panneau des Exifs
*/
private GridView gViewExif = null ;
/**
* La grille pour le panneau de Iptc
*/
private GridView gViewIptc = null ;
/**
* L'onglet des Exifs
*/
private Panel panneauExifGrid = null;
/**
* L'onglet des Iptc
*/
private Panel panneauIptcGrid = null ;
/**
* L'onglet des infos
*/
private Panel panneauInfoGrid = null ;
/**
* L'onglet des mots clés
*/
private ArbreMotsClesVue panneauMotsCles = null ;
/**
* Le champ commentaire
*/
private TextField commentaireGeneral = null ;
/**
* Le champ date
*/
private DateField dateImage = null ;
/**
* Le bouton de validation
*/
Button validerInfo = null ;
/**
* Barre de notation
*/
BarreNotationVue noteVue = null ;
/**
* Booleen d'instanciation
*/
boolean estInstancie = false ;
/**
* Constructeur sans argument (privé car ne doit pas être utilisé)
*/
@SuppressWarnings("unused")
private PanneauMetadonneesVue()
{
super() ;
}
/**
* Constructeur avec argument
* @param im
*/
public PanneauMetadonneesVue(ImageMediateur im)
{
super() ;
// on associe le médiateur
imediateur = im ;
// on crée et dispose les panneaux et les champs
panneauExifGrid = new Panel("Exif") ;
panneauIptcGrid = new Panel("Iptc") ;
panneauInfoGrid = new Panel("info") ;
panneauMotsCles = new ArbreMotsClesVue(im) ;
panneauMotsCles.setHeight("500px") ;
Panel sousPanneauInfosGenerales = new Panel("Infos Générales") ;
sousPanneauInfosGenerales.setLayout(new VerticalLayout());
sousPanneauInfosGenerales.setBorder(false) ;
sousPanneauInfosGenerales.setHeight(200);
sousPanneauInfosGenerales.setAutoWidth(true) ;
sousPanneauInfosGenerales.setMargins(5) ;
sousPanneauInfosGenerales.setPaddings(5) ;
sousPanneauInfosGenerales.setCollapsible(true) ;
Label labelComm = new Label("Commentaires :") ;
labelComm.setHeight("20px") ;
commentaireGeneral = new TextArea() ;
commentaireGeneral.setWidth("90%") ;
Label labelDate = new Label("Date :") ;
Label labelNote = new Label("Note :") ;
panneauMotsCles.setBorder(false) ;
labelDate.setHeight("20px") ;
dateImage = new DateField() ;
dateImage.setAutoWidth(true) ;
dateImage.setFormat("d/m/Y") ;
validerInfo = new Button("OK") ;
noteVue = new BarreNotationVue(im, 5) ;
sousPanneauInfosGenerales.add(labelComm) ;
sousPanneauInfosGenerales.add(commentaireGeneral) ;
sousPanneauInfosGenerales.add(labelDate) ;
sousPanneauInfosGenerales.add(dateImage) ;
sousPanneauInfosGenerales.add(labelNote) ;
sousPanneauInfosGenerales.add(noteVue) ;
sousPanneauInfosGenerales.add(validerInfo) ;
sousPanneauInfosGenerales.setAutoHeight(true);
panneauMotsCles.setAutoHeight(true) ;
panneauInfoGrid.setBorder(false);
panneauInfoGrid.setAutoHeight(true);
panneauInfoGrid.add(sousPanneauInfosGenerales) ;
panneauInfoGrid.add(panneauMotsCles) ;
this.add(panneauInfoGrid) ;
this.add(panneauExifGrid) ;
this.add(panneauIptcGrid) ;
gViewExif = new GridView();
gViewExif.setForceFit(true);
ExifGrid = new PropertyGridPanel() ;
ExifGrid.setId("meta_exif");
ExifGrid.setView(gViewExif);
ExifGrid.setNameText("Métadonnées Exif");
ExifGrid.setAutoWidth(true);
ExifGrid.setAutoHeight(true);
ExifGrid.setSorted(false);
gViewIptc = new GridView();
gViewIptc.setForceFit(true);
IptcGrid = new PropertyGridPanel() ;
IptcGrid.setId("meta_iptc");
IptcGrid.setView(gViewIptc);
IptcGrid.setNameText("Métadonnées IPTC");
IptcGrid.setAutoWidth(true);
IptcGrid.setAutoHeight(true);
IptcGrid.setSorted(false);
panneauExifGrid.add(ExifGrid);
panneauIptcGrid.add(IptcGrid);
// on ajoute les listeners
ajouterListeners() ;
// on effectue le rendu
this.doLayout(true) ;
}
private void ajouterListeners()
{
// on ajoute un écouteur
validerInfo.addListener(new ButtonListenerAdapter() {
 
// gestion du clic
public void onClick(Button button, EventObject e) {
button.focus() ;
// lors du clic sur le bouton valider on met à jour les commentaires et la date
getIMediateur().mettreAJourInfo(commentaireGeneral.getText(), dateImage.getRawValue(), noteVue.getNote()) ;
}
});
// gestion des clics dans la grille
ExifGrid.addGridCellListener(new GridCellListenerAdapter() {
 
// lors d'un clic d'une cellule
public void onCellClick(GridPanel grid, int rowIndex, int colIndex,
EventObject e) {
// on empeche l'édition
e.stopEvent() ;
ExifGrid.stopEditing() ;
}
 
// lors du double clic sur une cellule
public void onCellDblClick(GridPanel grid, int rowIndex,
int colIndex, EventObject e) {
// on empêche l'édition
e.stopEvent() ;
ExifGrid.stopEditing() ;
}
}) ;
IptcGrid.addGridCellListener(new GridCellListenerAdapter() {
 
// lors d'un clic d'une cellule
public void onCellClick(GridPanel grid, int rowIndex, int colIndex,
EventObject e) {
// on empeche l'édition
e.stopEvent() ;
ExifGrid.stopEditing() ;
}
 
// lors d'un double clic d'une cellule
public void onCellDblClick(GridPanel grid, int rowIndex,
int colIndex, EventObject e) {
// on empeche l'édition
e.stopEvent() ;
ExifGrid.stopEditing() ;
}
}) ;
}
/**
* Desactive visuellement ce panneau
*/
public void desactiverPanneau()
{
this.setDisabled(true) ;
}
/**
* Active visuellement ce panneau
*/
public void activerPanneau()
{
this.setDisabled(false) ;
}
/**
* Accesseur pour le médiateur
* @return le médiateur associé à la vue
*/
public ImageMediateur getIMediateur()
{
return imediateur ;
}
/**
* Méthode héritée de l'interface rafraichissable
* @param nouvelleDonnees les nouvelles données
* @param repandreRafraichissement le booleen de notification de mise à jour
*/
public void rafraichir(Object nouvelleDonnees, boolean repandreRafraichissement) {
// si on reçoit un tableau d'objets
if(nouvelleDonnees instanceof Object[])
{
// extrait infos, exifs et iptc
Object meta[] = (Object[])nouvelleDonnees ;
String[][] exif = (String[][])meta[0] ;
String[][] iptc = (String[][])meta[1] ;
String[][] gen = (String[][])meta[2] ;
NameValuePair[] exifSource = new NameValuePair[exif.length] ;
NameValuePair[] iptcSource = new NameValuePair[iptc.length] ;
int maxLength ;
if(exif.length <= iptc.length)
{
maxLength = iptc.length ;
}
else
{
maxLength = exif.length ;
}
for(int i = 0; i < maxLength ; i++)
{
if(i < exif.length && !exif[i][0].equals("null"))
{
exifSource[i] = new NameValuePair(exif[i][0],exif[i][1]) ;
}
if(i < iptc.length && !iptc[i][0].equals("null"))
{
iptcSource[i] = new NameValuePair(iptc[i][0],iptc[i][1]) ;
}
}
// on met à jour les champs avec la bonne valeur
commentaireGeneral.setValue(gen[0][1]) ;
dateImage.setRawValue(gen[1][1]) ;
// et on met à jour les données pour l'affichage
ExifGrid.setSource(exifSource);
IptcGrid.setSource(iptcSource);
 
}
}
 
/**
* Accesseur pour le panneau des mots clés
* @return the panneauMotsCles
*/
public ArbreMotsClesVue getPanneauMotsCles() {
return panneauMotsCles;
}
public BarreNotationVue getNoteVue() {
return noteVue ;
}
}
/trunk/src/org/tela_botanica/client/vues/ArbreMotsClesFiltreVue.java
New file
0,0 → 1,338
package org.tela_botanica.client.vues;
 
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.interfaces.Filtrable;
import org.tela_botanica.client.interfaces.Rafraichissable;
 
import com.google.gwt.user.client.ui.Label;
import com.gwtext.client.data.Node;
import com.gwtext.client.data.NodeTraversalCallback;
import com.gwtext.client.data.Tree;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.PanelListenerAdapter;
import com.gwtext.client.widgets.tree.TreeNode;
import com.gwtext.client.widgets.tree.TreePanel;
 
/**
* fenêtre de recherche affichant l'arbre des mots clés en lecture et un bouton
* cliquable
* @author aurelien
*
*/
public class ArbreMotsClesFiltreVue extends Panel implements Rafraichissable, Filtrable {
 
/**
* Le médiateur associé à la vue
*/
private ImageMediateur iMediateur = null ;
/**
* Les mots clés en cours
*/
private String motsClesEncours = "" ;
/**
* Le treepanel qui affiche l'arbre
*/
private TreePanel arbreMotsCles = null ;
/**
* booléen d'initialisation
*/
private boolean estInstancie = false ;
/**
* booléen d'etat
*/
private boolean filtreModifie = false ;
/**
* Constructeur sans argument (privé car ne doit pas être utilisé)
*/
@SuppressWarnings("unused")
private ArbreMotsClesFiltreVue()
{
super() ;
}
/**
* Constructeur avec paramètres
* @param im le médiateur à associer
*/
public ArbreMotsClesFiltreVue(ImageMediateur im)
{
// on crée le panel
super() ;
//this.setLayout(new VerticalLayout());
iMediateur = im ;
// on crée le conteneur de l'arbre
Label labelRecherche = new Label("Mots clés :") ;
arbreMotsCles = new TreePanel() ;
this.setPaddings(5) ;
this.setBorder(false) ;
this.setCollapsible(true) ;
this.setAutoWidth(true) ;
add(labelRecherche) ;
// on ajoute les listeners
ajouterListenersPanel() ;
estInstancie = false ;
}
/**
* 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
public void onRender(Component component) {
// on interdit le drag and drop dans l'arbre
arbreMotsCles.setEnableDD(false) ;
arbreMotsCles.setId("x-view-tree-filter") ;
arbreMotsCles.setAutoWidth(false) ;
arbreMotsCles.setAutoScroll(true) ;
arbreMotsCles.setBorder(false) ;
// on crée une racine pour l'arbre
TreeNode root = new TreeNode("Tags") ;
root.setId("racine_filtre") ;
String[] usObject = {"Mots clés" , "racine" } ;
root.setUserObject(usObject) ;
arbreMotsCles.setRootNode(root) ;
arbreMotsCles.setRootVisible(true) ;
arbreMotsCles.setBorder(false) ;
// on met en forme le layout
((Panel)component).add(arbreMotsCles) ;
// on ajoute les listeners d'évenements
ajouterListeners() ;
// et on demande l'arbre des mots clés
getIMediateur().obtenirArbreMotsCles(getIMediateur().getPanneauFiltres().getMotsClesFiltre()) ;
// enfin on considère le composant comme instancié
estInstancie = true ;
}
}) ;
}
/**
* ajoute les listeners pour les boutons et le cochage des mots clés
*/
private void ajouterListeners()
{
 
}
/**
* Méthode héritée de l'interface rafraichissable
*/
public void rafraichir(Object nouvelleDonnees,
boolean repandreRaffraichissement) {
// si on a reçu un arbre
if(nouvelleDonnees instanceof Tree)
{
Tree nouvelArbre = (Tree)nouvelleDonnees ;
// on vide tous les noeuds
arbreMotsCles.getRootNode().eachChild(new NodeTraversalCallback() {
public boolean execute(Node node) {
node.remove() ;
return true ;
}
}) ;
// et on recopie le nouvel arbre
copierFilsNoeud(nouvelArbre.getRootNode(), arbreMotsCles.getRootNode()) ;
// si l'arbre n'était pas encore considéré comme instancié
if(!estInstancie)
{
// on signale que oui
estInstancie = true ;
}
// l'état du filtre est réinitialisé
filtreModifie = false ;
show() ;
}
if(nouvelleDonnees instanceof TreeNode)
{
TreeNode nd = (TreeNode)nouvelleDonnees ;
// si le noeud n'existe pas déjà c'est un ajout
if(arbreMotsCles.getTree().getNodeById(nd.getId()+"_filtre") == null)
{
// donc on ne fait rien de spécial
}
// si le noeud existe déjà c'est un déplacement
else
{
// alors on supprime d'abord le noeud concerné
arbreMotsCles.getTree().getNodeById(nd.getId()+"_filtre").remove() ;
}
// on cherche le père du nouveau noeud
Node ndPereOriginal = nd.getParentNode() ;
String idPereFiltre = ndPereOriginal.getId()+"_filtre" ;
String[] usObj = (String[])nd.getUserObject() ;
TreeNode child = new TreeNode(usObj[0]) ;
child.setId(usObj[1]+"_filtre") ;
child.setChecked(false);
child.setUserObject(usObj) ;
arbreMotsCles.getNodeById(idPereFiltre).appendChild(child) ;
// et on ajoute le nouveau noeud à son père
copierFilsNoeud(nd, child) ;
}
// si on reçoit une string
if(nouvelleDonnees instanceof String)
{
String idSupp = (String)nouvelleDonnees+"_filtre" ;
// c'est une suppression et si le noeud existe bien
if(arbreMotsCles.getTree().getNodeById(idSupp) != null)
{
// on le supprime
arbreMotsCles.getTree().getNodeById(idSupp).remove() ;
}
}
}
/**
* Accesseur pour le médiateur
* @return le médiateur associé
*/
public ImageMediateur getIMediateur()
{
return iMediateur ;
}
/**
* Accesseur pour le panneau contenant l'arbre
* @return le panneau de l'arbre des mots clés
*/
public TreePanel getArbreMotsCles()
{
return arbreMotsCles ;
}
/**
* Méthode héritée de Filtrable
* renvoie le nom du filtre
*/
public String renvoyerNomFiltre() {
return "mots clés" ;
}
/**
* Renvoie un tableau contenant le nom du champ à filtrer et la valeur
* @return un tableau contenant le nom du champ à filtrer et sa valeur
*/
public String[] renvoyerValeursAFiltrer() {
valider() ;
String[] valeursFiltrees = {"ci_meta_mots_cles",motsClesEncours} ;
return valeursFiltrees ;
}
/**
* 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]+"_filtre") ;
child.setChecked(false);
child.setUserObject(usObj) ;
ndPereCopie.appendChild(child) ;
if(! ndNodeFils[i].isLeaf())
{
copierFilsNoeud(ndNodeFils[i],child) ;
}
}
}
}
 
/**
* Méthode héritée de Filtrable
* Renvoie l'état du filtre (modifié ou non)
*/
public boolean renvoyerEtatFiltre() {
return filtreModifie ;
}
public void valider()
{
if(estInstancie)
{
// 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 ;
}
});
// on suppose que le filtre a change
filtreModifie = true ;
}
}
 
}
/trunk/src/org/tela_botanica/client/vues/BarreOutilsVue.java
New file
0,0 → 1,91
package org.tela_botanica.client.vues;
 
import org.tela_botanica.client.image.ImageMediateur;
 
import com.gwtext.client.widgets.Toolbar;
import com.gwtext.client.widgets.ToolbarMenuButton;
 
 
/**
* Barre d'outils contenant le menu de gestion des images (accessible aussi par un clic droit dans la galerie)
* et d'autres menus et boutons utiles
* @author aurelien
*
*/
public class BarreOutilsVue extends Toolbar {
/**
* Un bouton qui sert à déployer le menu
*/
ToolbarMenuButton images = null ;
/**
* Un bouton qui sert à déployer le menu
*/
ToolbarMenuButton utilisateur = null ;
/**
* Le médiateur associé à la toolbar
*/
ImageMediateur iMediateur = null ;
/**
* Le menu de gestion des images
*/
MenuImageVue imageMenu = null ;
/**
* Le menu de gestion des filtres
*/
MenuFiltreVue filtreMenu = null ;
/**
* Le menu de gestion utilisateur
*/
MenuIdVue idMenu = null ;
 
/**
* Constructeur sans argument (ne doit pas être utilisé donc privé)
*/
@SuppressWarnings("unused")
private BarreOutilsVue()
{
super() ;
}
/**
* Constructeur avec paramètres
* @param im le médiateur à associer à la vue
*/
public BarreOutilsVue(ImageMediateur im) {
super() ;
iMediateur = im ;
imageMenu = new MenuImageVue(im) ;
filtreMenu = new MenuFiltreVue(im) ;
idMenu = new MenuIdVue(im) ;
images = new ToolbarMenuButton("Fichiers",imageMenu) ;
utilisateur = new ToolbarMenuButton("Utilisateur",idMenu) ;
this.addButton(images) ;
this.addButton(utilisateur) ;
}
 
 
/**
* @return the images
*/
public ToolbarMenuButton getImages() {
return images;
}
 
 
/**
* @return the iMediateur
*/
public ImageMediateur getIMediateur() {
return iMediateur;
}
 
}
/trunk/src/org/tela_botanica/client/vues/GalerieImageVue.java
New file
0,0 → 1,309
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.interfaces.VueListable;
 
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.XTemplate;
import com.gwtext.client.data.FieldDef;
import com.gwtext.client.data.IntegerFieldDef;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.RecordDef;
import com.gwtext.client.data.Store;
import com.gwtext.client.data.StringFieldDef;
import com.gwtext.client.util.Format;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.DataView;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.ContainerListenerAdapter;
import com.gwtext.client.widgets.event.DataViewListenerAdapter;
 
/**
* Galerie d'images miniatures
* Avec barre de pagination
* @author aurelien
*/
public class GalerieImageVue extends Panel implements Rafraichissable, VueListable {
 
/**
* instance du médiateur
*/
private ImageMediateur iMediateur = null;
/**
* Dataview, littéralement "vue de données" qui permet de définir la manière d'afficher les données
*/
private DataView dView = null;
/**
* Dataview, littéralement "vue de données" qui permet de définir la manière d'afficher les données
*/
private Store st = null;
/**
* Barre de pagination gérant l'affichage d'un nombre donné d'élements par page et la navigation entre eux
*/
private pageToolBarVue pt = null ;
/**
* Booleen indiquant si la galerie est instanciée ou pas
*/
private boolean estInstancie = false ;
 
/**
* Constructeur sans argument, privé car ne doit pas être utilisé
*/
@SuppressWarnings("unused")
private GalerieImageVue()
{
super() ;
}
/**
* Constructeur avec argument
* @param im le médiateur avec lequel la vue va communiquer
*/
public GalerieImageVue(ImageMediateur im) {
super("Galerie");
iMediateur = im;
// on ajoute des listeners au composant tout entier
this.addListener(new ContainerListenerAdapter() {
 
// pour gagner du temps on n'instancie la vue en elle même que lors du premier affichage (lazy rendering)
public void onShow(Component component) {
 
if (!estInstancie) {
initialiser();
}
}
 
});
// et on ajoute la tool bar
pt = new pageToolBarVue(im) ;
this.setBottomToolbar(pt) ;
 
}
 
/**
* Ajoute tous les listeners nécessaires à l'intercation utilisateur avec la vue de données
*/
public void ajouterListenersDataView() {
 
// ajout de listeners pour la gestion de la selection
// dans la galerie
dView.addListener(new DataViewListenerAdapter() {
// gestion du clic sur une image
public void onClick(DataView source, int index, Element node,
EventObject e) {
// on en notifie le médiateur
getIMediateur().clicGalerieImage(index, node, e);
 
}
 
// gestion du clic droit
public void onContextMenu(DataView source, int index, Element node,
EventObject e) {
 
// on stoppe l'évenement
e.stopEvent();
// et on notifie le médiateur
getIMediateur().montrerContextMenu(e);
 
}
 
// gestion du double clic
public void onDblClick(DataView source, int index, Element node,
EventObject e) {
 
// on notife le mediateur
getIMediateur().clicGalerieImage(index, node, e);
}
 
// gestion des actions en fonction de la selection
public void onSelectionChange(DataView view, Element[] selections) {
 
// s'il n'y a aucun élement sélectionné
if (selections.length <= 0) {
// on en notifie le médiateur
getIMediateur().aucuneSelection();
} else {
// sinon on notifie le médiateur
getIMediateur().selection();
// et on lui demande de synchroniser la séléction avec les autres vues
getIMediateur().synchroniserSelection("galerie");
}
}
 
});
}
 
/**
* Accesseur pour la dataview
* @return la dataview
*/
public DataView getDView() {
return dView;
}
 
/**
* Renvoie les ids des images sélectionnées
* @return un tableau de String contenant les identifiants des images sélectionnées
*/
public String[] getIdSelectionnees() {
Record[] selection = getDView().getSelectedRecords();
int taille = selection.length;
String id_selection[] = new String[taille];
 
for (int i = 0; i < selection.length; i++) {
 
id_selection[i] = selection[i].getAsString("num_image");
}
 
return id_selection;
}
 
/**
* Accesseur pour le médiateur
* @return le médiateur associé à la vue
*/
public ImageMediateur getIMediateur() {
return iMediateur;
}
 
/**
* Accesseur pour le store
* @return le store associé à la vue
*/
public Store getSt() {
return st;
}
/**
* Accesseur pour la toolbar
* @return la toolbar associée à la vue
*/
public pageToolBarVue getToolBarVue()
{
return pt ;
}
 
/**
* Fonction d'initialisation du contenu (appelée lors du premier affichage de la liste)
*/
public void initialiser() {
// Preparation de la dataview et du template
// le template va créer une div contenant une image
// pour chacune des photos
final XTemplate template = new XTemplate(
new String[] {
"<tpl for='.'>",
"<div class='thumb-wrap' id='{num_image}'>",
"<div class='thumb'><img src='{url_image_M}' title='{num_image}'></div>",
"<span>{nom}</span></div>", "</tpl>",
"<div class='x-clear'></div>" });
// pour des raisons de performances on compile le template en une fonction
template.compile();
 
// la dataview affichera les images en accord avec le template
// cree precedemment
dView = new DataView("div.thumb-wrap") {
 
public void prepareData(Data data) {
data.setProperty("shortName", Format.ellipsis(data
.getProperty("num_image"), 15));
}
};
dView.setTpl(template);
 
// parametre d'affichage de la dataview
this.setAutoScroll(true);
dView.setAutoHeight(true);
dView.setMultiSelect(true);
dView.setOverCls("x-view-over");
dView.setEmptyText("Aucune image à afficher");
 
// creation du store
FieldDef defNumImage = new IntegerFieldDef("num_image");
FieldDef defDatImage = new StringFieldDef("dat_image");
FieldDef defLieImage = new StringFieldDef("lie_image");
FieldDef defAppImage = new StringFieldDef("app_image");
FieldDef defUrlImageS = new StringFieldDef("url_image_S");
FieldDef defUrlImageM = new StringFieldDef("url_image_M");
FieldDef defUrlImage = new StringFieldDef("url_image");
FieldDef[] defTab = { defNumImage, defDatImage, defLieImage,
defAppImage, defUrlImageS, defUrlImageM, defUrlImage };
RecordDef rd = new RecordDef(defTab);
st = new Store(rd);
dView.setStore(st);
 
this.getDView().setLoadingText("chargement");
 
// ajouts de la gestion des evenements pour la dataview
ajouterListenersDataView();
 
this.add(dView);
// enfin on envoie une demande de données au médiateur
getIMediateur().obtenirPhotoGalerie(this);
// et on déclare le composant comme instancié
estInstancie = true ;
}
 
/**
* Méthode héritée de l'interface rafraichissable
*/
public void rafraichir(Object nouvelleDonnees,
boolean repandreRafraichissement) {
 
// si l'objet reçu est un store
if (nouvelleDonnees instanceof Store) {
st = (Store) nouvelleDonnees;
// on le charge
st.load();
// on l'affecte à la vue
dView.setStore(st);
// et on rafrachit la vue
dView.refresh();
}
 
// si le composant doit répandre le rafraichissement
if (repandreRafraichissement) {
// il en notifie le médiateur en lui donnant une copie des données et en notifiant qu'il en est l'expéditeur
getIMediateur().synchroniserDonneesZoomListeGalerie(
nouvelleDonnees, this);
}
// si c'est la première mise à jour que l'on reçoit
if(!estInstancie)
{
// alors le composant est considéré comme instancié
estInstancie = true ;
}
}
 
/**
* Méthode héritée de l'interface VueListable
* Sélectionne les images dans la galerie suivant les identifiants donnés en paramètres
* @param ids les identifiants des images à sélectionner
*/
public void selectionnerImages(int[] ids) {
 
getDView().select(ids);
 
}
}
/trunk/src/org/tela_botanica/client/vues/pageToolBarVue.java
New file
0,0 → 1,410
package org.tela_botanica.client.vues;
 
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.interfaces.Rafraichissable;
 
import com.gwtext.client.core.EventCallback;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.Template;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.SimpleStore;
import com.gwtext.client.data.Store;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.Toolbar;
import com.gwtext.client.widgets.ToolbarButton;
import com.gwtext.client.widgets.ToolbarTextItem;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.form.ComboBox;
import com.gwtext.client.widgets.form.Field;
import com.gwtext.client.widgets.form.TextField;
import com.gwtext.client.widgets.form.event.ComboBoxListenerAdapter;
import com.gwtext.client.widgets.form.event.TextFieldListenerAdapter;
 
 
/**
* Barre de pagination asynchrone avec filtrage des touches et accès directs et séquentiels à une page
* @author aurelien
*
*/
public class pageToolBarVue extends Toolbar implements Rafraichissable {
/**
* Instance du médiateur à qui on notifie les évnènements
*/
private ImageMediateur iMediateur = null ;
/**
* Bouton précédent
*/
private ToolbarButton prevPage = new ToolbarButton() ;
/**
* Bouton suivant
*/
private ToolbarButton suivPage = new ToolbarButton() ;
/**
* Numéro de la page courante (attention, commence à zéro pour des raisons pratiques)
*/
private int pageCourante = 0 ;
/**
* Nombre de page total
*/
private int pageTotale = 1 ;
/**
* Nombre d'élements total
*/
private int nbElement = 0 ;
/**
* Nombre d'élément par page
*/
private int taillePage = 0 ;
/**
* Texte statique de la toolbar 1
*/
private ToolbarTextItem page = new ToolbarTextItem("Page ") ;
/**
* Affichage de la page courante
*/
private TextField champPage = new TextField(""+(pageCourante+1)) ;
/**
* Affichage de "sur pageTotale "
*/
private ToolbarTextItem surTotalPage = new ToolbarTextItem(" sur "+pageTotale) ;
/**
* Texte statique de la toolbar 2
*/
private ToolbarTextItem afficherNbElem = new ToolbarTextItem("Afficher ") ;
/**
* Combobox permettant de selectionner le nombre d'élements à afficher par page
* et donc de changer la variable taillePage
*/
private ComboBox selecteurTaillePage = new ComboBox() ;
/**
* Texte statique de la toolbar 3
*/
private ToolbarTextItem nbElemParPage = new ToolbarTextItem(" images par page ") ;
/**
* Affiche l'intervalle des éléments contenus dans la page
*/
private ToolbarTextItem intervalleElements = new ToolbarTextItem("Images "+pageCourante*taillePage+" sur "+nbElement) ;
 
/**
* retourne le mediateur associe à la barre
*/
public ImageMediateur getImediateur()
{
return iMediateur ;
}
/***
* constructeur sans argument (privé car ne doit pas être utilisé)
*/
@SuppressWarnings("unused")
private pageToolBarVue()
{
super() ;
}
/**
* constructeur avec paramètres
* @param im le médiateur à associer à la barre
*/
public pageToolBarVue(ImageMediateur im)
{
super() ;
iMediateur = im ;
// on dispose un peu de texte et quelques espaces pour séparer les éléments
addButton(prevPage) ;
addSpacer() ;
addItem(page) ;
addField(champPage) ;
addItem(surTotalPage) ;
addSpacer() ;
addButton(suivPage) ;
champPage.setWidth(30) ;
addSpacer() ;
addItem(afficherNbElem) ;
prevPage.setIcon("page_prev.png") ;
suivPage.setIcon("page_suiv.png") ;
// le store contient les valeur possibles pour les tailles de page
final Store store = new SimpleStore(new String[]{"nb_page"}, getNbPages());
store.load();
// le template definit ce que l'on affiche pour chaque element du store dans la combobox
final Template tp = new Template("<div class=\"x-combo-list-item\">"
+ "{nb_page}"
+ "<div class=\"x-clear\"></div></div>");
tp.compile();
selecteurTaillePage.setTpl(tp) ;
selecteurTaillePage.setStore(store) ;
selecteurTaillePage.setWidth(40) ;
selecteurTaillePage.setEditable(false) ;
addField(selecteurTaillePage) ;
selecteurTaillePage.setValue("50") ;
selecteurTaillePage.setWidth(50) ;
addItem(nbElemParPage) ;
// on remplit l'espace pour que l'intervalle d'élement se place à droite de la barre
addFill() ;
addItem(intervalleElements) ;
addSpacer() ;
// on ajoute les différents listeners
ajouterListeners() ;
}
/**
* ajoute les différents listeners nécessaires au bon fonctionnement des éléments de la barre de pagination
*/
private void ajouterListeners()
{
// boutons suivants et précédents
prevPage.addListener(new ButtonListenerAdapter() {
 
public void onClick(Button button, EventObject e) {
// si la page courante n'est pas la première
if(pageCourante > 0)
{
// on décrémente la page courante de 1
pageCourante -- ;
// on rafraichit l'affichage
rafraichirNumeroPage() ;
// et on notifie le médiateur de l'évenement
getImediateur().changerNumeroPage(pageCourante) ;
}
}
}) ;
suivPage.addListener(new ButtonListenerAdapter() {
public void onClick(Button button, EventObject e) {
// si la page courante n'est pas la dernière
if(pageCourante < pageTotale -1)
{
// on incrémente la page courante de 1
pageCourante ++ ;
// on rafraichit l'affichage
rafraichirNumeroPage() ;
// et on notifie le médiateur de l'évenement
getImediateur().changerNumeroPage(pageCourante) ;
}
}
}) ;
champPage.addListener(new TextFieldListenerAdapter() {
 
public void onSpecialKey(Field field, EventObject e) {
// on teste si la touche entrée a été pressée
if(e.getKey() == EventObject.ENTER)
{
int nouvellePage = pageCourante ;
// on teste avec parseInt si la valeur entrée est un entier
try
{
nouvellePage = Integer.parseInt(champPage.getRawValue()) ;
}
// si ce n'est pas le cas alors on remet le numéro de page correct
catch(NumberFormatException nfe)
{
rafraichirNumeroPage() ;
champPage.focus(true) ;
return ;
}
// si la conversion reussit on verifie s'il est nécessaire de changer de page
// et si la nouvelle est comprise dans l'intervalle des pages existantes (0..pageTotale)
if(nouvellePage != pageCourante + 1 && nouvellePage > 0 && nouvellePage <= pageTotale)
{
// le cas échéant, on charge la nouvelle page et on notifie le médiateur
changerPageCourante(nouvellePage - 1) ;
getImediateur().changerNumeroPage(pageCourante) ;
 
}
else
{
// sinon on reaffiche l'ancien numero de page sans rien changer
rafraichirNumeroPage() ;
champPage.focus(true) ;
}
}
}
public void onFocus(Field field) {
champPage.focus(true) ;
}
});
// pour éviter de se compliquer la vie, on filtre tous les charactères non numériques
champPage.addKeyPressListener(new EventCallback() {
 
public void execute(EventObject e) {
// si c'est un numerique
if(Character.isDigit((char)e.getCharCode()))
{
// on laisse passer
return ;
}
// si c'est la touche entrée ou backspace (valider ou effacer)
if(e.getKey() == EventObject.ENTER || e.getKey() == EventObject.BACKSPACE)
{
// on laisse passer
return ;
}
else
{
// sinon on remet le numero de page correct et on annule l'évenement
rafraichirNumeroPage() ;
e.stopEvent() ;
}
}
}) ;
// listener pour la selection dans la combobox
selecteurTaillePage.addListener(new ComboBoxListenerAdapter() {
public void onSelect(ComboBox comboBox, Record record, int index) {
String nouvelleTaillePageString = comboBox.getStore().getRecordAt(index).getAsString("nb_page") ;
int nouvelleTaillePage = Integer.parseInt(nouvelleTaillePageString) ;
// si la taille de page est différente de l'ancienne
if(nouvelleTaillePage != taillePage)
{
// on la change
changerTaillePage(nouvelleTaillePage) ;
}
// et on met la valeur à jour dans la combobox
comboBox.setValue(nouvelleTaillePageString) ;
}
}) ;
}
/**
* Met à jour les affichage sur les numéros de pages et d'intervalle d'éléments
* à partir des variables de classes
*/
public void rafraichirNumeroPage()
{
surTotalPage.setText(" sur "+pageTotale) ;
if(nbElement == 0)
{
champPage.setValue(""+(0)) ;
// on met simplement à jour l'intervalle qui contient toujours le même nombre d'éléments
intervalleElements.setText("Images 0 - 0 sur 0") ;
}
else
{
champPage.setValue(""+(pageCourante+1)) ;
// si la page n'est pas la dernière
if(pageCourante + 1 != pageTotale)
{
// sauf pour la dernière page qui contient souvent moins d'élements que le nombre d'élements par page
intervalleElements.setText("Images "+pageCourante*taillePage+" - "+(pageCourante+1)*taillePage+" sur "+nbElement) ;
}
else
{
// on met simplement à jour l'intervalle qui contient toujours le même nombre d'éléments
intervalleElements.setText("Images "+pageCourante*taillePage+" - "+nbElement+" sur "+nbElement) ;
}
}
}
/**
* Met à jour la page en cours
* @param nouvellePageCourante la nouvelle page en cours
*/
public void changerPageCourante(int nouvellePageCourante)
{
pageCourante = nouvellePageCourante ;
}
/**
* Methode héritée de l'interface rafraichissable
*/
public void rafraichir(Object nouvelleDonnees,
boolean repandreRaffraichissement) {
// si on reçoit un tableau de int
if(nouvelleDonnees instanceof int[])
{
int [] page = (int[])nouvelleDonnees ;
// le premier élement est le nombre de pages totales
pageTotale = page[0] ;
// le second la page en cours
pageCourante = page[1] ;
// le troisième la taille de la page
taillePage = page[2] ;
// et le dernier le nombre total d'éléments
nbElement = page[3] ;
// si la page courante dépasse la page totale (cas normalement improbable car géré en amont)
// on met le numéro de page à la page courante -1 (car la page courante est comptée à partir
// de zéro)
if(pageCourante >= pageTotale && pageCourante != 0)
{
pageCourante = pageTotale - 1 ;
// le cas échéant on en notifie le médiateur
getImediateur().changerNumeroPage(pageCourante) ;
}
}
// enfin on rafraichit les informations affichées à partir des nouvelles variables de classes mises à jour
rafraichirNumeroPage() ;
}
/**
* Renvoie les différents intervalles de pages possibles
* @return un tableau de tableau de string qui contient les différentes taille de pages
*/
public String[][] getNbPages()
{
String[][] pages = {{"200"},{"100"},{"50"},{"20"},{"10"}} ;
return pages ;
}
 
/**
* Envoie au médiateur une demande pour modifier la taille de la page
* (qui va à son tour faire les modifications nécessaires)
* @param nouvelleTaillePage la nouvelle taille de page (élement appartenant au tableau renvoyé par getNbPages())
*/
public void changerTaillePage(int nouvelleTaillePage) {
getImediateur().changerTaillePage(nouvelleTaillePage) ;
}
/**
* Selectionne la valeur correspond à celle passée en paramètre dans la combobox (si elle existe)
* @param nouvelleTaillePage la nouvelle taille de page
*/
public void selectionnerTaillePage(int nouvelleTaillePage) {
selecteurTaillePage.setValue(""+nouvelleTaillePage) ;
}
}
/trunk/src/org/tela_botanica/client/vues/MenuIdVue.java
New file
0,0 → 1,86
package org.tela_botanica.client.vues;
 
import org.tela_botanica.client.image.ImageMediateur;
 
import com.gwtext.client.core.EventObject;
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;
 
public class MenuIdVue extends Menu {
/**
* Le médiateur associé à la vue
*/
private ImageMediateur iMediateur ;
/**
* Item pour le changement d'utilisateur
*/
private Item changerId = null ;
/**
* Constructeur sans argument (privé car ne doit être utilisé)
*/
@SuppressWarnings("unused")
private MenuIdVue()
{
super();
}
/**
* Constructeur avec paramètre
* @param im le médiateur à associer
*/
public MenuIdVue(ImageMediateur im)
{
super() ;
iMediateur = im ;
// on construit le menu
changerId = new Item("Changer d'utilisateur") ;
addItem(changerId) ;
// on ajoute les listeners
ajouterListeners() ;
}
/**
* Ajoute les listeners pour la gestions des évènements
*/
private void ajouterListeners()
{
this.addListener(new MenuListenerAdapter() {
 
// gestion du clic sur un item
public void onItemClick(BaseItem item, EventObject e) {
// si c'est la recherche par commentaires
if(item.equals(changerId))
{
// on notifie le médiateur
getIMediateur().afficherMenuId() ;
}
// enfin, on cache le menu
hide() ;
}
}) ;
}
/**
* Accesseur pour le médiateur
* @return le médiateur associé à la vue
*/
public ImageMediateur getIMediateur()
{
return iMediateur ;
}
 
}
/trunk/src/org/tela_botanica/client/vues/DateFiltreVue.java
New file
0,0 → 1,148
package org.tela_botanica.client.vues;
 
 
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.interfaces.Filtrable;
import org.tela_botanica.client.interfaces.Rafraichissable;
 
import com.google.gwt.user.client.ui.Label;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.form.DateField;
 
/**
* Classe implémentant un filtre qui permet de rechercher une aimge par rapport à la date associée,
* des critères plus fins viendront compléter cela
* @author aurelien
*
*/
public class DateFiltreVue extends Panel implements Rafraichissable, Filtrable {
 
/**
* Le médiateur associé à la vue
*/
private ImageMediateur iMediateur = null ;
/**
* Le widget calendrier
*/
private DateField filtreDate = null ;
 
/**
* Booleen d'état du filtre
*/
private boolean filtreModifie = false ;
 
/**
* Constructeur sans argument (privé car ne doit pas être utilisé)
*/
@SuppressWarnings("unused")
private DateFiltreVue()
{
super() ;
}
/**
* Constructeur avec arguments
* @param im le médiateur à associer
*/
public DateFiltreVue(ImageMediateur im)
{
super() ;
setPaddings(5) ;
setCollapsible(true) ;
setBorder(false) ;
iMediateur = im ;
Label labelRecherche = new Label("Date :") ;
add(labelRecherche) ;
// on crée le calendrier et on définit le format de la date "jj/mm/aaaa"
filtreDate = new DateField() ;
filtreDate.setAutoWidth(true) ;
filtreDate.setFormat("d/m/Y") ;
add(filtreDate);
ajouterListeners() ;
}
/**
* Ajoute les listeners
*/
public void ajouterListeners()
{
}
/**
* Méthode héritée de l'interface rafraichissable
*/
public void rafraichir(Object nouvelleDonnees,
boolean repandreRaffraichissement) {
filtreModifie = false ;
}
/**
* Méthode héritée de l'interface filtrable
*/
public void valider() {
filtreModifie = true ;
}
 
/**
* Accesseur pour le médiateur
* @return le médiateur associé à la vue
*/
@SuppressWarnings("unused")
private ImageMediateur getIMediateur() {
return iMediateur ;
}
 
/**
* Méthode héritée de l'interface filtrable
*/
public boolean renvoyerEtatFiltre() {
return filtreModifie ;
}
 
/**
* Méthode héritée de l'interface filtrable
*/
public String renvoyerNomFiltre() {
return "Recherche par date" ;
}
 
/**
* Méthode héritée de l'interface filtrable
*/
public String[] renvoyerValeursAFiltrer() {
// si la date est valide
if(filtreDate.isValid())
{
// on en sépare les composants
String dt = filtreDate.getRawValue() ;
String[] dates = dt.split("/") ;
if(dates.length == 3)
{
// qu'on réassemble dans un autre format (américain) pour la base de donnée "aaaa-mm-jj"
String dateFormatee = dates[2]+"-"+dates[1]+"-"+dates[0] ;
String[] valeursFiltres = {"ci_meta_date" , dateFormatee } ;
return valeursFiltres ;
}
}
// si la date n'estp as valide on renvoie une chaine vide (ce qui correspond à n'importe qu'elle date)
String dateFormatee = "" ;
String[] valeursFiltres = {"ci_meta_date" , dateFormatee } ;
return valeursFiltres ;
}
 
}
/trunk/src/org/tela_botanica/client/vues/ListeImageVue.java
New file
0,0 → 1,437
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.interfaces.VueListable;
 
import com.gwtext.client.core.EventObject;
import com.gwtext.client.data.FieldDef;
import com.gwtext.client.data.IntegerFieldDef;
import com.gwtext.client.data.Record;
import com.gwtext.client.data.RecordDef;
import com.gwtext.client.data.Store;
import com.gwtext.client.data.StringFieldDef;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.event.ContainerListenerAdapter;
import com.gwtext.client.widgets.grid.CellMetadata;
import com.gwtext.client.widgets.grid.ColumnConfig;
import com.gwtext.client.widgets.grid.ColumnModel;
import com.gwtext.client.widgets.grid.GridPanel;
import com.gwtext.client.widgets.grid.Renderer;
import com.gwtext.client.widgets.grid.RowSelectionModel;
import com.gwtext.client.widgets.grid.event.GridRowListener;
import com.gwtext.client.widgets.grid.event.RowSelectionListenerAdapter;
 
/**
* Liste d'image composée de miniatures et d'information sur l'image, implémente
* l'interface rafraichissable et l'interface vueListable
*
* @author aurelien
*/
public class ListeImageVue extends GridPanel implements Rafraichissable,
VueListable {
 
/**
* Le médiateur associé à la vue
*/
private ImageMediateur iMediateur = null;
/**
* Config de colonne
*/
private ColumnConfig numImage;
/**
* Config de colonne
*/
private ColumnConfig urlImage;
/**
* Config de colonne
*/
private ColumnConfig lieImage;
/**
* Config de colonne
*/
private ColumnConfig datImage;
/**
* Config de colonne
*/
private ColumnConfig appImage;
/**
* Config de colonne
*/
private ColumnConfig noteImage;
/**
* Modele de colonnes
*/
private ColumnModel modeleColonnes;
 
/**
* Booleen d'instanciation
*/
private boolean estInstancie = false;
 
/**
* Store qui contient les données à afficher
*/
private Store st = null;
/**
* Configuration des colonnes du store
*/
private ColumnConfig cl = null;
/**
* Barre de pagination
*/
private pageToolBarVue bt = null ;
 
/**
* Constructeur sans arguments (privé car ne doit pas être utilisé)
*/
private ListeImageVue()
{
super() ;
}
/**
* Constructeur avec argument
* @param im le médiateur à associer
*/
public ListeImageVue(ImageMediateur im) {
 
new ListeImageVue() ;
 
this.setId("listeImageGrid");
// on associe le médiateur
this.iMediateur = im;
// on place la barre de pagination
bt = new pageToolBarVue(iMediateur);
setBottomToolbar(bt) ;
 
// on construit le modèle de colonnes
numImage = new ColumnConfig("numéro", "num_image", 30, true, new Renderer() {
 
public String render(Object value, CellMetadata cellMetadata,
Record record, int rowIndex, int colNum, Store store) {
String ImgNum = record.getAsString("num_image");
return "<div class=\"centered-list\">"+ ImgNum +"</div>";
}
}) ;
datImage = new ColumnConfig("date", "dat_image", 120, true, new Renderer() {
 
public String render(Object value, CellMetadata cellMetadata,
Record record, int rowIndex, int colNum, Store store) {
String ImgDat = record.getAsString("dat_image");
if(ImgDat == null)
{
ImgDat = " " ;
}
return "<div class=\"centered-list\">"+ ImgDat +"</div>";
}
}) ;
lieImage = new ColumnConfig("lieu", "lie_image", 120, true, new Renderer() {
 
public String render(Object value, CellMetadata cellMetadata,
Record record, int rowIndex, int colNum, Store store) {
String ImgLie = record.getAsString("lie_image");
if(ImgLie == null)
{
ImgLie = " " ;
}
return "<div class=\"centered-list\">"+ ImgLie +"</div>";
}
}) ;
appImage = new ColumnConfig("appareil", "app_image", 120, true, new Renderer() {
 
public String render(Object value, CellMetadata cellMetadata,
Record record, int rowIndex, int colNum, Store store) {
String ImgApp = record.getAsString("app_image");
if(ImgApp == null)
{
ImgApp = " " ;
}
return "<div class=\"centered-list\">"+ ImgApp +"</div>";
}
}) ;
// la colonne url possède une méthode de rendu spéciale
urlImage = new ColumnConfig("Image", "url_image_S", 30, true,
new Renderer() {
 
public String render(Object value,
CellMetadata cellMetadata, Record record,
int rowIndex, int colNum, Store store) {
// on affiche une div contenant l'image pointée par l'url
String ImgUrl = record.getAsString("url_image_S");
String ImgNum = record.getAsString("num_image");
return "<div class=\"img-list centered-list\"> <img src=\"" + ImgUrl
+ "\" title='" + ImgNum + "'> </div>";
}
 
});
noteImage = new ColumnConfig("note", "note_image", 80, true,
new Renderer()
{
public String render(Object value, CellMetadata cellMetadata,
Record record, int rowIndex, int colNum, Store store) {
String htmlImage = "" ;
int noteImg = record.getAsInteger("note_image") ;
if(noteImg >= 0)
{
htmlImage += "<div class=\"img-note centered-list\">" ;
for(int i = 0 ; i <= noteImg ; i++)
{
htmlImage += "<img src=\"note-on.gif\">" ;
}
htmlImage += "</div>" ;
}
return htmlImage ;
}
}) ;
// on associe le modèle de colonnes
ColumnConfig[] cm = {numImage, urlImage, datImage, lieImage, appImage, noteImage};
modeleColonnes = new ColumnModel(cm);
this.setColumnModel(modeleColonnes);
this.setAutoScroll(true);
this.setAutoWidth(true);
this.setEnableColumnResize(true);
 
// creation du store
FieldDef defNumImage = new IntegerFieldDef("num_image");
FieldDef defDatImage = new StringFieldDef("dat_image");
FieldDef defLieImage = new StringFieldDef("lie_image");
FieldDef defAppImage = new StringFieldDef("app_image");
FieldDef defUrlImageS = new StringFieldDef("url_image_S");
FieldDef defUrlImageM = new StringFieldDef("url_image_M");
FieldDef defUrlImage = new StringFieldDef("url_image");
FieldDef defNoteImage = new StringFieldDef("note_image");
FieldDef[] defTab = { defNumImage, defDatImage, defLieImage,
defAppImage, defUrlImageS, defUrlImageM, defUrlImage, defNoteImage };
RecordDef rd = new RecordDef(defTab);
st = new Store(rd);
// on associe le store
this.setStore(st);
this.getView().setAutoFill(true);
// on crée un masque de chargement qui s'affichera lors des mises à jour
this.setLoadMask("chargement");
// on ajoute les listeners
ajouterListeners();
 
}
 
/**
* Ajoute les listeners pour la gestion des évènements
*/
private void ajouterListeners() {
this.addListener(new ContainerListenerAdapter() {
 
public void onHide(Component component) {
 
}
 
// lors du premier rendu on demande les données qui sont déjà contenues dans la galerie qui est le premier élément affiché
public void onRender(Component component) {
 
if (!isEstInstancie()) {
setEstInstancie(true);
getIMediateur().synchroniserSelection("galerie");
}
}
 
public void onShow(Component component) {
 
}
 
});
 
this.addGridRowListener(new GridRowListener() {
// gestion du clic sur une ligne
public void onRowClick(GridPanel grid, int rowIndex, EventObject e) {
 
// on notifie le médiateur et on lui passe le nuémro de ligne
getIMediateur().clicListeImage(rowIndex);
}
// gestion du clic droit
public void onRowContextMenu(GridPanel grid, int rowIndex,
EventObject e) {
// on stoppe l'évenement pour empecher le navigateur d'afficher son propre menu
e.stopEvent() ;
// on notifie le médiateur en lui passant l'évenement
getIMediateur().montrerContextMenu(e);
}
 
// gestion du double clic
public void onRowDblClick(GridPanel grid, int rowIndex,
EventObject e) {
// on notifie le médiateur en lui passant le numéro de ligne
getIMediateur().doubleClicListeImage(rowIndex);
}
});
 
this.getSelectionModel().addListener(new RowSelectionListenerAdapter() {
 
// gestion de la sélection
public void onSelectionChange(RowSelectionModel sm) {
 
// si on a rien de sélectionné
if (sm.getCount() <= 0) {
// on notifie le médiateur (qui désactive notamment l'accès à certaines infos)
getIMediateur().aucuneSelection();
} else {
// sinon on notifie le médiateur
getIMediateur().selection();
// et on lui demande de synchroniser la selection avec les autres vues
getIMediateur().synchroniserSelection("liste");
}
}
});
}
 
/**
* Méthode héritée de l'interface VueListable
* Sélectionne les images dans la galerie suivant les identifiants donnés en paramètres
*/
public String[] getIdSelectionnees() {
Record[] selection = this.getSelectionModel().getSelections();
int taille = selection.length;
String id_selection[] = new String[taille];
 
for (int i = 0; i < selection.length; i++) {
 
id_selection[i] = selection[i].getAsString("num_image");
}
 
return id_selection;
}
 
/**
* Accesseur pour la config de colonnes
* @return la config de colonnes
*/
public ColumnConfig getCl() {
return cl;
}
/**
* Accesseur pour le médiateur
* @return le médiateur associé
*/
public ImageMediateur getIMediateur() {
return iMediateur;
}
 
/**
* Accesseur pour le modèle de colonnes
* @return le modèle de colonnes
*/
public ColumnModel getModeleColonnes() {
return modeleColonnes;
}
 
/**
* Accesseur pour le store
* @return le store contenant les données
*/
public Store getSt() {
return st;
}
/**
* Accesseur pour le booleen d'instanciation
* @return le booleen d'instanciation
*/
public boolean isEstInstancie() {
return estInstancie;
}
 
/**
* Méthode héritée de l'interface rafraichissable
* @param nouvelleDonnees les nouvelles données
* @param repandreRafraichissement le booleen de notification du rafraichissement
*/
public void rafraichir(Object nouvelleDonnees,
boolean repandreRafraichissement) {
 
// si on reçoit un store
if (nouvelleDonnees instanceof Store) {
 
// on affecte celui-ci comme gestionnaire de données
st = (Store) nouvelleDonnees;
st.load();
// et on reconfigure et rafraichit la vue
this.reconfigure(st, this.getColumnModel());
}
 
// si on doit répandre l'évenement
if (repandreRafraichissement) {
// on notifie le médiateur avec une copie des données
getIMediateur().synchroniserDonneesZoomListeGalerie(
nouvelleDonnees, this);
}
}
 
/**
* Sélectionne des enregistrements donné
* @param sel un tableau d'enregistrement à selectionner
*/
public void selectionnerEnregistrements(Record[] sel) {
 
if (isEstInstancie()) {
getSelectionModel().clearSelections();
getSelectionModel().selectRecords(sel);
}
}
/**
* Accesseur pour la toolbar de pagination
* @return la toolbar de pagination
*/
public pageToolBarVue getToolBarVue()
{
return bt ;
}
 
/**
* Setteur pour le booleen d'instanciation
* @param estInstancie la nouvelle valeur du booleen
*/
public void setEstInstancie(boolean estInstancie) {
this.estInstancie = estInstancie;
}
 
public void mettreAjourInfos(String commentaires, String date, String note) {
for (int i = 0; i < getSelectionModel().getCount(); i++) {
getSelectionModel().getSelections()[i].set("note_image", note) ;
getSelectionModel().getSelections()[i].set("dat_image", date) ;
}
}
 
}
/trunk/src/org/tela_botanica/client/vues/PanneauFiltresVues.java
New file
0,0 → 1,128
package org.tela_botanica.client.vues;
 
import org.tela_botanica.client.image.ImageMediateur;
 
import com.gwtext.client.core.EventObject;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.layout.VerticalLayout;
 
 
/**
* Panneau contenant les filtres qu'on peut appliquer aux images
* @author aurelien
*
*/
public class PanneauFiltresVues extends Panel {
 
/**
* Le médiateur associé
*/
@SuppressWarnings("unused")
private ImageMediateur iMediateur = null ;
/**
* L'arbre pour la recherche par mots clés
*/
private ArbreMotsClesFiltreVue motsClesFiltres = null ;
/**
* La barre de recherche par commentaires
*/
private BarreRechercheFiltreVue commFiltresVues = null ;
/**
* Recherche par date
*/
private DateFiltreVue dateFiltreVues = null ;
/**
* Bouton de validation
*/
private Button valider = null ;
/**
* Construcuteur sans argument (privé car on ne doit pas l'utiliser)
*/
@SuppressWarnings("unused")
private PanneauFiltresVues()
{
super() ;
}
/**
* Constructeur avec arguments
* @param im le médiateur à associer
*/
public PanneauFiltresVues(ImageMediateur im)
{
super("Rechercher des images") ;
iMediateur = im ;
this.setCollapsible(true) ;
setLayout(new VerticalLayout()) ;
commFiltresVues = new BarreRechercheFiltreVue(im) ;
add(commFiltresVues) ;
dateFiltreVues = new DateFiltreVue(im) ;
add(dateFiltreVues) ;
motsClesFiltres = new ArbreMotsClesFiltreVue(im) ;
add(motsClesFiltres) ;
Panel panelValidation = new Panel() ;
valider = new Button("Rechercher") ;
panelValidation.add(valider) ;
panelValidation.setBorder(false) ;
add(panelValidation) ;
valider.addListener(new ButtonListenerAdapter() {
 
public void onClick(Button button, EventObject e) {
iMediateur.obtenirPhotoGalerie(iMediateur.getGalerieImage()) ;
}
}) ;
}
/**
* Accesseur pour le filtre des mots clés
* @return le filtre des mots clés
*/
public ArbreMotsClesFiltreVue getMotsClesFiltre()
{
return motsClesFiltres ;
}
/**
* Accesseur pour le filtre par commentaire
* @return le filtre des commentaires
*/
public BarreRechercheFiltreVue getBarreRecherche()
{
return commFiltresVues ;
}
 
/**
* Renvoie un booléen indiquant si un des filtres a été modifié
* @return true sur un des filtres est modifié, false sinon
*/
public boolean renvoyerEtatFiltre() {
return (motsClesFiltres.renvoyerEtatFiltre() || commFiltresVues.renvoyerEtatFiltre() || dateFiltreVues.renvoyerEtatFiltre() ) ;
}
/**
* Renvoie un tableau à 2 niveaux contenant des paires "nom_de_filtre", "valeur"
* @return un tableau contenant les noms et les valeurs à filtrer
*/
public String[][] renvoyerValeursAFiltrer()
{
String[][] filtres = { motsClesFiltres.renvoyerValeursAFiltrer(), commFiltresVues.renvoyerValeursAFiltrer() , dateFiltreVues.renvoyerValeursAFiltrer() } ;
return filtres ;
}
 
}
/trunk/src/org/tela_botanica/client/vues/ArbreMotsClesVue.java
New file
0,0 → 1,466
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 considiè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) {
// 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 ;
}
getArbreMotsCles().getNodeById(node.getId()).getUI().toggleCheck(false) ;
}
// 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()) ;
// 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 && 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 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)) ;
}
 
}