Subversion Repositories eFlore/Applications.cel

Rev

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);
                        }
                }
        }
}