Rev 225 | Rev 324 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
package org.tela_botanica.client.vues.image;
import org.tela_botanica.client.image.ImageMediateur;
import org.tela_botanica.client.interfaces.Rafraichissable;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.KeyboardListenerCollection;
import com.google.gwt.user.client.ui.LoadListener;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.MouseWheelListener;
import com.google.gwt.user.client.ui.MouseWheelVelocity;
import com.google.gwt.user.client.ui.ToggleButton;
import com.google.gwt.user.client.ui.Widget;
import com.gwtext.client.core.AnimationConfig;
import com.gwtext.client.core.Direction;
import com.gwtext.client.core.DomConfig;
import com.gwtext.client.core.EventObject;
import com.gwtext.client.core.Ext;
import com.gwtext.client.core.ExtElement;
import com.gwtext.client.core.Function;
import com.gwtext.client.core.RegionPosition;
import com.gwtext.client.dd.DragData;
import com.gwtext.client.dd.DragSource;
import com.gwtext.client.dd.DropTarget;
import com.gwtext.client.dd.DropTargetConfig;
import com.gwtext.client.widgets.Button;
import com.gwtext.client.widgets.Component;
import com.gwtext.client.widgets.Container;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.ToolTip;
import com.gwtext.client.widgets.Toolbar;
import com.gwtext.client.widgets.ToolbarButton;
import com.gwtext.client.widgets.ToolbarTextItem;
import com.gwtext.client.widgets.event.ButtonListener;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.event.PanelListenerAdapter;
import com.gwtext.client.widgets.grid.GridDragData;
import com.gwtext.client.widgets.layout.BorderLayout;
import com.gwtext.client.widgets.layout.BorderLayoutData;
import com.gwtext.client.widgets.menu.Menu;
/**
* 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;
/**
* Identifiant de l'image
*/
private String idImage = "0" ;
/**
* Booleen d'initalisation général
*/
private boolean initialise = false;
/**
* Booleen d'initalisation du conteneur d'image
*/
private boolean conteneurInitialise = false;
private ToolTip tp = new ToolTip("<div class=\"x-tooltip-help\"> Double cliquez pour revenir à la vue précédente, utilisez la roulette ou les boutons fléchés pour faire défiler les images </div>") ;
/**
* true pour animer les transitions des animations
*/
private boolean animerTransition = false;
/**
* duree des animation
*/
private float dureeAnimation = (float) 0.15 ;
/**.
* boolean de gestion du double clic
*/
private boolean enClic = false;
private ToolbarButton modeZoom = null;
private ToolbarTextItem valeurZoom = new ToolbarTextItem("x 1");
private int sourisX = 0;
private int sourisY = 0;
private int sourisXFin = 0;
private int sourisYFin = 0;
private float niveauZoom = 1;
private float pasZoom = new Float(0.1);
private int maxZoom = 10;
private float minZoom = new Float(0.5);
protected boolean scroll = 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();
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
//imageConteneur.sinkEvents(Event.ONMOUSEWHEEL);
// l'image de base est vide
image.setUrl("vide.jpg");
this.setLayout(new BorderLayout());
prev.setWidth("60px");
suiv.setWidth("60px");
modeZoom = new ToolbarButton("Mode Zoom");
Toolbar tb = new Toolbar();
tb.addButton(modeZoom);
tb.addItem(valeurZoom);
//setTopToolbar(tb);
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;
configDragAndDrop() ;
// on ajoute les listeners
ajouterListeners();
tp.setDismissDelay(1050);
tp.applyTo(image.getElement()) ;
}
/**
* 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) {
//niveauZoom = 1;
// 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
if (infos[0] != null && infos[1] != null && infos[2] != null && infos[3] != null) {
getImage().setUrl(infos[0]);
int x = Integer.parseInt(infos[1]);
int y = Integer.parseInt(infos[2]);
setTailleImage(x, y);
setIdImage(infos[3]) ;
//verifierEtRetaillerImage();
}
} else {
// sinon on met une image vide
getImage().setUrl("vide.jpg");
}
}
/**
* 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);
}
public void masquerChargement() {
ExtElement imgEl = Ext.get(imageConteneur.getElement());
if(imgEl != null && !imgEl.isMasked()) {
imgEl.mask("Chargement");
}
}
public void demasquerChargement() {
ExtElement imgEl = Ext.get(imageConteneur.getElement());
if(imgEl != null && imgEl.isMasked()) {
imgEl.unmask();
}
}
/**
* Ajoute les listeners pour la gestions d'évènement
*/
public void ajouterListeners() {
modeZoom.addListener(new ButtonListenerAdapter() {
public void onClick(Button button, EventObject e) {
// TODO Auto-generated method stub
if(modeZoom.isPressed()) {
modeZoom.toggle(false);
} else {
modeZoom.toggle(true);
}
}
public void onToggle(Button button, boolean pressed) {
if(pressed) {
scroll = true;
image.addStyleName("img-curseur-depl");
} else {
scroll = false;
image.removeStyleName("img-curseur-depl");
niveauZoom = 1;
verifierEtRetaillerImage();
Ext.get(image.getElement()).center(imageConteneur.getElement());
}
}
});
image.addLoadListener(new LoadListener() {
public void onError(Widget sender) {
// TODO Auto-generated method stub
}
public void onLoad(Widget sender) {
/*int max = Math.min(imageConteneur.getHeight(), imageConteneur.getWidth());
int[] tailleImage = calculerDimensions(getTailleImage(), max, max);
ExtElement imgElement = Ext.get(image.getElement());
if(animerTransition) {
AnimationConfig a = new AnimationConfig() ;
a.setDuration((float) dureeAnimation);
imgElement.setHeight(tailleImage[1], a);
imgElement.setWidth(tailleImage[0], a);
} else {
imgElement.setHeight(tailleImage[1], false);
imgElement.setWidth(tailleImage[0], false);
}*/
verifierEtRetaillerImage();
Ext.get(image.getElement()).center(imageConteneur.getElement());
demasquerChargement();
}
});
image.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
if(!scroll) {
if(enClic) {
getIMediateur().doubleClicZoomImage();
} else {
Timer t = new Timer() {
public void run() {
enClic = false;
}
};
enClic = true;
t.schedule(800);
}
}
}
});
image.addMouseWheelListener(new MouseWheelListener() {
public void onMouseWheel(Widget sender, MouseWheelVelocity velocity) {
if(velocity.getDeltaY() > 0) {
if(scroll) {
zoomOut();
} else {
suiv.click();
}
} else {
if(scroll) {
zoomIn();
} else {
prev.click();
}
}
}
});
image.addMouseListener(new MouseListener() {
public void onMouseDown(Widget sender, int x, int y) {
if(scroll) {
Event.getCurrentEvent().preventDefault();
scroll = true;
sourisX = x;
sourisY = y;
image.addStyleName("img-curseur-depl");
}
}
public void onMouseEnter(Widget sender) {
// TODO Auto-generated method stub
}
public void onMouseLeave(Widget sender) {
// TODO Auto-generated method stub
}
public void onMouseMove(Widget sender, int x, int y) {
sourisXFin = x;
sourisYFin = y;
Event.getCurrentEvent().preventDefault();
}
public void onMouseUp(Widget sender, int x, int y) {
if(scroll) {
Event.getCurrentEvent().preventDefault();
if(sourisX - sourisXFin > 0) {
Ext.get(image.getElement()).move(Direction.LEFT, sourisX - sourisXFin, false);
}
if(sourisXFin - sourisX > 0) {
Ext.get(image.getElement()).move(Direction.RIGHT, sourisXFin - sourisX, false);
}
if(sourisY - sourisYFin > 0) {
Ext.get(image.getElement()).move(Direction.UP, sourisY - sourisYFin, false);
}
if(sourisYFin - sourisY > 0) {
Ext.get(image.getElement()).move(Direction.DOWN, sourisYFin - sourisY, false);
}
}
}
});
// 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
masquerChargement();
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
masquerChargement();
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
int max = Math.min(imageConteneur.getHeight(), imageConteneur.getWidth());
int[] tailleImage = new int[2];
ExtElement imgElement = Ext.get(image.getElement());
if(max == imageConteneur.getHeight()) {
//tailleImage[0] = getTailleImage()[0];
//tailleImage[1] = max;
imgElement.setHeight(max, false);
} else {
//tailleImage[1] = getTailleImage()[0];
//tailleImage[0] = max;
imgElement.setWidth(max, false);
}
//int[] tailleImage = calculerDimensions(getTailleImage(), max, max);
//imgElement.
/*if(animerTransition) {
AnimationConfig a = new AnimationConfig() ;
a.setDuration((float) dureeAnimation);
imgElement.setHeight(tailleImage[1], a);
imgElement.setWidth(tailleImage[0], a);
} else {
imgElement.setHeight(tailleImage[1], false);
imgElement.setWidth(tailleImage[0], false);
}*/
String strZoom = ""+niveauZoom+"";
strZoom = strZoom.substring(0,3);
valeurZoom.setText("x "+strZoom);
}
public int[] calculerDimensions(int[] tailleXY, double tailleMax, double tailleConteneur) {
float[] tailleXYf = {new Float(tailleXY[0]),new Float(tailleXY[1])} ;
float tailleOr = Math.min(new Float(tailleMax),new Float(tailleConteneur)) ;
float maxTaille = Math.max(tailleXYf[1],tailleXYf[0]) ;
float[] XYresize = new float[2];
if(maxTaille == tailleXY[0]) {
float rapport = tailleXYf[1]/tailleXYf[0] ;
XYresize[0] = tailleOr ;
XYresize[1] = tailleOr*rapport ;
}else {
float rapport = tailleXYf[0]/tailleXYf[1] ;
XYresize[1] = tailleOr ;
XYresize[0] = tailleOr*rapport ;
}
int[] res = {(int)Math.round(XYresize[0]*niveauZoom),(int) Math.round(XYresize[1]*niveauZoom)} ;
return res;
}
public void configDragAndDrop()
{
// on fabrique la nouvelle configuration
// les éléments sur lesquels on fait du drag 'n drop doivent tous avoir le même ddGroup
DropTargetConfig dtc = new DropTargetConfig();
dtc.setdDdGroup("DragGroupName");
//La drop target permet de gérer l'évenement onDrop sur l'élement courant
@SuppressWarnings("unused")
DropTarget tg = new DropTarget(this, dtc)
{
public boolean notifyDrop(DragSource source, EventObject e, DragData data){
// si on reçoit des données provenant d'une grille
if(data instanceof GridDragData)
{
// on appelle le médiateur
return iMediateur.lierObsDD(source, e, data,getId()) ;
}
return false ;
}
public String notifyOver(DragSource source, EventObject e, DragData data){
return "x-dd-drop-ok";
}
};
}
/**
* 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;
}
/**
* Acesseurs pour l'identifiant de l'image
* @return l'id de l'image
*/
public String getIdImage()
{
return idImage ;
}
/**
* 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;
}
/**
* Setteur pour l'identifiant de l'image
* @param id le nouvel identifiant
*/
public void setIdImage(String id)
{
idImage = id ;
}
/**
* 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;
}
/**
* Accesseur pour le conteneur de l'image
* @return le conteur de l'image
*/
public Panel getImageConteneur() {
return imageConteneur;
}
private void zoomOut() {
if(niveauZoom >= minZoom) {
niveauZoom -= pasZoom;
if(niveauZoom <= minZoom) {
niveauZoom = minZoom;
}
verifierEtRetaillerImage();
gererDecalage(false);
}
}
private void zoomIn() {
if(niveauZoom < maxZoom ) {
niveauZoom += pasZoom;
if(niveauZoom >= maxZoom) {
niveauZoom = maxZoom;
}
verifierEtRetaillerImage();
gererDecalage(true);
}
}
private void gererDecalage(boolean in) {
float nZoom = niveauZoom;
if(niveauZoom < 1) {
nZoom = 1/niveauZoom;
}
if(!in) {
int diffX = imageConteneur.getWidth()/2 - sourisX;
int diffY = imageConteneur.getHeight()/2 - sourisY;
if(diffX > 0) {
Ext.get(image.getElement()).move(Direction.RIGHT, (int)((diffX/maxZoom)/nZoom), false);
}
if(-diffX > 0) {
Ext.get(image.getElement()).move(Direction.LEFT, (int)(-(diffX/maxZoom)/nZoom), false);
}
if(diffY > 0) {
Ext.get(image.getElement()).move(Direction.DOWN, (int)((diffY/maxZoom)/nZoom), false);
}
if(-diffY > 0) {
Ext.get(image.getElement()).move(Direction.UP, (int)(-(diffY/maxZoom)/nZoom), false);
}
} else {
int diffX = imageConteneur.getWidth()/2;
int diffY = imageConteneur.getHeight()/2;
if(diffX > 0) {
Ext.get(image.getElement()).move(Direction.LEFT, (int)((diffX/maxZoom)/nZoom), false);
}
if(-diffX > 0) {
Ext.get(image.getElement()).move(Direction.RIGHT, (int)((-diffX/maxZoom)/nZoom), false);
}
if(diffY > 0) {
Ext.get(image.getElement()).move(Direction.UP, (int)((diffY/maxZoom)/nZoom), false);
}
if(-diffY > 0) {
Ext.get(image.getElement()).move(Direction.DOWN, (int)(-(diffY/maxZoom)/nZoom), false);
}
}
}
}