/* --------------------------------------------------------------------------------- */
/* -                                 Classe Grid                                   - */
/* --------------------------------------------------------------------------------- */
/* - Description :                                                                 - */
/* -    Permet l'affichage, la gestion et la manipulation d'un tableau de cellules - */
/* -    Differentes methodes offrent la possibilite d'effectuer des drag&drop, des - */
/* -    copier-coller, des effets de mirroir...                                    - */
/* --------------------------------------------------------------------------------- */
/* -          Projet Internet 97, DESS ISI Filiere Logiciels, ESSI                 - */
/* -                                                                               - */
/* - Etudiants :                                                                   - */
/* -    Sacha RAYBAUD                                                              - */
/* -    Frederic RUBINO                                                            - */
/* -                                                                               - */
/* - Professeurs responsables :                                                    - */
/* -    Michel BUFFA                                                               - */
/* -    Jean-Michel LEON                                                           - */
/* --------------------------------------------------------------------------------- */

/**
 *  Description :                                                                 
 *     Permet l'affichage, la gestion et la manipulation d'un tableau de cellules 
 *     Differentes methodes offrent la possibilite d'effectuer des drag&drop, des 
 *     copier-coller, des effets de mirroir...                                    
 * @version     1.0 08/03/97 
 * @author      Sacha Raybaud, Frederic Rubino
 */

import java.util.Vector;
import java.awt.Panel;
import java.awt.Color;
import java.awt.Scrollbar;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Graphics;
import java.awt.Button;
import java.awt.Component;
import java.awt.Event;
import java.awt.Point;


public class Grid extends Panel
{
  final static int MIN_WIDTH           = 100;   // Taille min de la longueur d'une grid
  final static int MIN_HEIGHT          = 100;   // Taille min de la hauteur d'une grid
  final static int DEFAULT_WIDTH       = 300;   // Taille par defaut de la longueur d'une grid
  final static int DEFAULT_HEIGHT      = 200;   // Taille par defaut de la hauteur d'une grid
  final static int MIN_NB_ROWS         = 1;    
  final static int MIN_NB_COLS         = 1;
  final static int DEFAULT_NB_ROWS     = 5;
  final static int DEFAULT_NB_COLS     = 5;
  final static int MIN_BORDER_SIZE     = 1;
  final static int DEFAULT_BORDER_SIZE = 3;

  Vector     grid;  
  Vector     cellsSelected;
  int        currentCellPosX;
  int        currentCellPosY; 
  int        firstPosX;
  int        firstPosY;
  int        secondPosX;
  int        secondPosY;
  int        nbRows;
  int        nbCols;
  int        width;
  int        height;
  int        realWidth;
  int        realHeight;
  boolean    tooLongGridW;
  boolean    tooLongGridH;
  String     title;
  int        borderSize;
  Color      borderColor;
  boolean    visibleBorder;
  Color      fieldsColor;
  Color      fieldsTextColor;
  boolean    visibleFields;
  GridLayout gridLayout;
  GridLayout layoutFieldH;
  GridLayout layoutFieldV;  
  GridLayout layoutTitle;
  BorderLayout borderLayout;
  Panel      basePanel;
  Panel      gridPanel;
  Panel      panelFieldV;
  Panel      panelFieldH;
  Panel      panelTitle;
  boolean    dynamicSize;
  boolean    interactive;
  Scrollbar  scrollBarH;
  Scrollbar  scrollBarV;
  boolean    scrollBarHMode;
  boolean    scrollBarVMode;
  int        tScrollBarX;
  int        tScrollBarY;
  int        tailleCellX;
  int        tailleCellY;


/* --------------------------------------------------------------------------------- */
/* -                                 CONSTRUCTEURS                                 - */
/* --------------------------------------------------------------------------------- */

  /**
   * Creer une Grid avec les valeurs par defaut.
   */
  public Grid()
  {
 
    super();
 
    cellsSelected = new Vector();
    grid = new Vector();
 
    nbRows = DEFAULT_NB_ROWS;
    nbCols = DEFAULT_NB_COLS;
    width  = DEFAULT_WIDTH;
    height = DEFAULT_HEIGHT;
    realWidth  = DEFAULT_WIDTH;
    realHeight = DEFAULT_HEIGHT;
    title = null;
    borderSize = DEFAULT_BORDER_SIZE;
    borderColor = Color.gray;
    visibleBorder = true;
    fieldsColor = Color.gray;
    fieldsTextColor = Color.white;
    visibleFields = true;
    dynamicSize = false;
    interactive = false;
    scrollBarHMode = true;
    scrollBarVMode = true;
    scrollBarH = new Scrollbar(Scrollbar.HORIZONTAL);
    scrollBarV = new Scrollbar(Scrollbar.VERTICAL);
 
    borderLayout = new BorderLayout();
    setLayout(borderLayout);
 
    basePanel  = new Panel();
    basePanel.setLayout(null);
 
    gridPanel   = new Panel();
 
    basePanel.add(gridPanel);
 
    add("Center",basePanel); 
 
    if (visibleFields)
      {
      if (visibleBorder)
        {
          layoutFieldH = new GridLayout(1,nbCols+1,borderSize,borderSize);
          layoutFieldV = new GridLayout(nbRows,1,borderSize,borderSize);
          gridLayout = new GridLayout(nbRows,nbCols,borderSize,borderSize);
        }
      else
        {
          layoutFieldH = new GridLayout(1,nbCols+1);
          layoutFieldV = new GridLayout(nbRows,1);
          gridLayout = new GridLayout(nbRows,nbCols);
 
        }
      panelFieldH = new Panel();
      panelFieldV = new Panel();
      panelTitle  = new Panel();
 
      layoutTitle= new GridLayout(1,1);
      panelFieldV.setLayout(layoutFieldV);
      panelFieldH.setLayout(layoutFieldH);
      panelTitle.setLayout(layoutTitle);
      }
    else
      {
        if (visibleBorder)
          gridLayout = new GridLayout(nbRows,nbCols,borderSize,borderSize);
        else
          gridLayout = new GridLayout(nbRows,nbCols);
      }
 
    gridPanel.setLayout(gridLayout);
 
    for (int cmpt = 0; cmpt <= nbCols; cmpt++)
      {
        if (cmpt==0)
          {
            Field l = new Field("",fieldsColor,fieldsTextColor);
            grid.addElement(l);
            if (visibleFields)
              panelTitle.add(l);
          }
        else
          {
            Field l = new Field((new Integer(cmpt)).toString(),fieldsColor,fieldsTextColor);
            grid.addElement(l);
            if (visibleFields)
              panelFieldH.add(l);
          }
      }
    for (int cmpt1 = 1; cmpt1 <= nbRows; cmpt1++)
      {
        for (int cmpt2 = 0; cmpt2 <= nbCols; cmpt2++)
          {
            if (cmpt2==0)
              {
                Field l = new Field((new Integer(cmpt1)).toString(),fieldsColor,fieldsTextColor);
                grid.addElement(l);
                if (visibleFields)
                  panelFieldV.add(l);
              }
            else
              {
                Cell c = new Cell();
                grid.addElement(c);
                gridPanel.add(c);
              }
          }
      }
    
    setTailleCell();
 
    tooLongGridW = (width < realWidth);
    tooLongGridH = (height < realHeight);
    if (tooLongGridW)
      add("South",scrollBarH);
 
    if (tooLongGridH)
      add("East",scrollBarV);
 
    if (scrollBarHMode && scrollBarVMode && tooLongGridW && tooLongGridH)
      resize(width+18,height+18);
    else
      if (scrollBarHMode && tooLongGridW)
        resize(width,height+18);
      else
        if (scrollBarVMode && tooLongGridH)
          resize(width+18,height);
        else
          resize(width,height);   
 
   //  resize(width,height);
    
    //basePanel.add(gridPanel);
 
    gridPanel.resize(realWidth-tailleCellX,realHeight-tailleCellY);
    gridPanel.setBackground(borderColor);
 
    if (visibleFields)
      {
        gridPanel.move(tailleCellX,tailleCellY);
 
        basePanel.add(panelFieldH);
        panelFieldH.move(tailleCellX,0);
        panelFieldH.resize(realWidth-tailleCellX,tailleCellY);
    
        basePanel.add(panelFieldV);   
        panelFieldV.move(0,tailleCellY);
        panelFieldV.resize(tailleCellX,realHeight-tailleCellY);
 
        basePanel.add(panelTitle);
        panelTitle.move(0,0);
        panelTitle.resize(tailleCellX,tailleCellY);
        setTitle(title);
      }
 
    basePanel.resize(width,height);
    repaint();
  }



//   /**
//    * Creer une Grid avec les valeurs par defaut.
//    */
//   public Grid()
//   {

//     super();

//     cellsSelected = new Vector();
//     grid = new Vector();

//     nbRows = DEFAULT_NB_ROWS;
//     nbCols = DEFAULT_NB_COLS;
//     width  = DEFAULT_WIDTH;
//     height = DEFAULT_HEIGHT;
//     realWidth  = DEFAULT_WIDTH;
//     realHeight = DEFAULT_HEIGHT;
//     tooLongGridW = false;
//     tooLongGridH = false;
//     title = null;
//     borderSize = DEFAULT_BORDER_SIZE;
//     borderColor = Color.gray;
//     visibleBorder = true;
//     fieldColor = Color.gray;
//     fieldsTextColor = Color.white;
//     visibleFields = true;
//     dynamicSize = false;
//     interactive = false;
//     scrollBarHMode = true;
//     scrollBarVMode = true;
//     scrollBarH = new Scrollbar(Scrollbar.HORIZONTAL);
//     scrollBarV = new Scrollbar(Scrollbar.VERTICAL);

//     borderLayout = new BorderLayout();
//     setLayout(borderLayout);

//     basePanel  = new Panel();
//     basePanel.setLayout(null);

//     gridPanel   = new Panel();

//     basePanel.add(gridPanel);

//     add("Center",basePanel); 

//     if (visibleFields)
//       {
//       if (visibleBorder)
// 	{
// 	  layoutFieldH = new GridLayout(1,nbCols+1,borderSize,borderSize);
// 	  layoutFieldV = new GridLayout(nbRows,1,borderSize,borderSize);
// 	  gridLayout = new GridLayout(nbRows,nbCols,borderSize,borderSize);
// 	}
//       else
// 	{
// 	  layoutFieldH = new GridLayout(1,nbCols+1);
// 	  layoutFieldV = new GridLayout(nbRows,1);
// 	  gridLayout = new GridLayout(nbRows,nbCols);

// 	}
//       panelFieldH = new Panel();
//       panelFieldV = new Panel();
//       panelTitle  = new Panel();

//       layoutTitle= new GridLayout(1,1);
//       panelFieldV.setLayout(layoutFieldV);
//       panelFieldH.setLayout(layoutFieldH);
//       panelTitle.setLayout(layoutTitle);
//       }
//     else
//       {
// 	if (visibleBorder)
// 	  gridLayout = new GridLayout(nbRows,nbCols,borderSize,borderSize);
// 	else
// 	  gridLayout = new GridLayout(nbRows,nbCols);
//       }

//     gridPanel.setLayout(gridLayout);

//     for (int cmpt = 0; cmpt <= nbCols; cmpt++)
//       {
// 	if (cmpt==0)
// 	  {
// 	    Field l = new Field("",fieldsColor,fieldsTextColor);
// 	    grid.addElement(l);
// 	    if (visibleFields)
// 	      panelTitle.add(l);
// 	  }
// 	else
// 	  {
// 	    Field l = new Field((new Integer(cmpt)).toString(),fieldsColor,fieldsTextColor);
// 	    grid.addElement(l);
// 	    if (visibleFields)
// 	      panelFieldH.add(l);
// 	  }
//       }
//     for (int cmpt1 = 1; cmpt1 <= nbRows; cmpt1++)
//       {
// 	for (int cmpt2 = 0; cmpt2 <= nbCols; cmpt2++)
// 	  {
// 	    if (cmpt2==0)
// 	      {
// 		Field l = new Field((new Integer(cmpt1)).toString(),fieldsColor,fieldsTextColor);
// 		grid.addElement(l);
// 		if (visibleFields)
// 		  panelFieldV.add(l);
// 	      }
// 	    else
// 	      {
// 		Cell c = new Cell();
// 		grid.addElement(c);
// 		gridPanel.add(c);
// 	      }
// 	  }
//       }
    
//     setTailleCell();
//     resize(width,height);
    
//     //basePanel.add(gridPanel);

//     gridPanel.resize(realWidth,realHeight);
//     gridPanel.setBackground(borderColor);

//     if (visibleFields)
//       {
// 	gridPanel.move(tailleCellX,tailleCellY);

// 	basePanel.add(panelFieldH);
// 	panelFieldH.move(tailleCellX,0);
// 	panelFieldH.resize(realWidth,tailleCellY);
    
// 	basePanel.add(panelFieldV);   
// 	panelFieldV.move(0,tailleCellY);
// 	panelFieldV.resize(tailleCellX,realHeight);

// 	basePanel.add(panelTitle);
// 	panelTitle.move(0,0);
// 	panelTitle.resize(tailleCellX,tailleCellY);
// 	setTitle(title);
//       }

//     basePanel.resize(width,height);
//     repaint();
//   }


  /**
   * Creer une Grid avec les valeurs de l'utilisateur.
   * @param nbC Nombre de colonnes de la Grid
   * @param nbR Nombre de Lignes de la Grid
   * @param w Longueur de la Grid (en pixels)
   * @param h Hauteur de la Grid (en pixels)
   * @param rw Longueur de la Grid dans sa totalite (en pixels)
   * @param rh Hauteur de la Grid dans sa totalite (en pixels)
   * @param t Titre de la Grid
   * @param bS Taille de la bordure de la Grid (en pixels)
   * @param bC Couleur de la bordure de la Grid 
   * @param fC Couleur du fond des champs de la Grid
   * @param fT Couleur du texte des champs de la Grid
   * @param cC Couleur de fond des cellules de la Grid
   * @param vB Booleen indiquant si la bordure doit etre visible
   * @param vF Booleen indiquant si les champs doivent etre visibles
   * @param dS Booleen indiquant si la Grid doit etre redimensionnee en fct du contenu
   * @param iT Booleen indiquant si l'utilisateur peut interagir la Grid
   * @param smH Booleen indiquant si une Scrollbar horizontale doit apparaitre en fct de la taille de la Grid
   * @param smV Booleen indiquant si une Scrollbar verticale doit apparaitre en fct de la taille de la Grid
   */
  public Grid(int nbC,int nbR,int w,int h,int rw,int rh,String t,int bS,Color bC,Color fC,Color fT,Color cC,boolean vB,boolean vF,boolean dS,boolean iT,boolean smH,boolean smV)
  {

    super();

    cellsSelected = new Vector();
    grid = new Vector();

    if (nbR < MIN_NB_ROWS) 
      nbRows = MIN_NB_ROWS;
    else 
      nbRows = nbR;
    if (nbC < MIN_NB_COLS) 
      nbCols = MIN_NB_COLS;
    else 
      nbCols = nbC;
    if (w < MIN_WIDTH)
      width = MIN_WIDTH;
    else 
      width = w;
    if (h < MIN_HEIGHT)
      height = MIN_HEIGHT;
    else
      height = h;
    if (rw < MIN_WIDTH)
      realWidth = MIN_WIDTH;
    else 
      realWidth = rw;
    if (rh < MIN_HEIGHT)
      realHeight = MIN_HEIGHT;
    else
      realHeight = rh;

    System.out.println(nbCols+" "+nbRows);

 //    tooLongGridW = (width < realWidth);
//     tooLongGridH = (height < realHeight);
//     System.out.println("tooW"+tooLongGridW);
// System.out.println("tooH"+ tooLongGridH);

    //if (title==null)
    // title = new String("");
    // else
    title = t;
    if (title==null)
      title = "";

    if (bS < MIN_BORDER_SIZE)
      borderSize = MIN_BORDER_SIZE;
    else
      borderSize = bS;
    borderColor = bC;
    visibleBorder = vB;

    fieldsColor = fC;
    fieldsTextColor = fT;
    visibleFields = vF;
    dynamicSize = dS;
    interactive = iT;

    borderLayout = new BorderLayout();
    setLayout(borderLayout);

    basePanel  = new Panel();
    basePanel.setLayout(null);

    gridPanel = new Panel();
    basePanel.add(gridPanel);
    add("Center",basePanel);

    if (visibleFields)
      {
	if (visibleBorder)
	  {
	    layoutFieldH = new GridLayout(1,nbCols+1,borderSize,borderSize);
	    layoutFieldV = new GridLayout(nbRows,1,borderSize,borderSize);
	    gridLayout = new GridLayout(nbRows,nbCols,borderSize,borderSize);
	  }
	else
	  {
	    layoutFieldH = new GridLayout(1,nbCols+1);
	    layoutFieldV = new GridLayout(nbRows,1);
	    gridLayout = new GridLayout(nbRows,nbCols);
	    
	  }
	panelFieldH = new Panel();
	panelFieldV = new Panel();
	panelTitle  = new Panel();
	
	layoutTitle= new GridLayout(1,1);
	panelFieldV.setLayout(layoutFieldV);
	panelFieldH.setLayout(layoutFieldH);
	panelTitle.setLayout(layoutTitle);
      }
    else
      {
	if (visibleBorder)
	  gridLayout = new GridLayout(nbRows,nbCols,borderSize,borderSize);
	else
	  gridLayout = new GridLayout(nbRows,nbCols);
      }

    gridPanel.setLayout(gridLayout);

  
   for (int cmpt = 0; cmpt <= nbCols; cmpt++)
      {
	if (cmpt==0)
	  {
	    Field l = new Field(title,fieldsColor,fieldsTextColor);
	    grid.addElement(l);
	    if (visibleFields)
	      panelTitle.add(l);
	  }
	else
	  {
	    Field l = new Field((new Integer(cmpt)).toString(),fieldsColor,fieldsTextColor);
	    grid.addElement(l);
	    if (visibleFields)
	      panelFieldH.add(l);
	  }
      }
    for (int cmpt1 = 1; cmpt1 <= nbRows; cmpt1++)
      {
	for (int cmpt2 = 0; cmpt2 <= nbCols; cmpt2++)
	  {
	    if (cmpt2==0)
	      {
		Field l = new Field((new Integer(cmpt1)).toString(),fieldsColor,fieldsTextColor);
		grid.addElement(l);
		if (visibleFields)
		  panelFieldV.add(l);
	      }
	    else
	      {
		Cell c = new Cell(null,cC,false,true);
		grid.addElement(c);
		gridPanel.add(c);
	      }
	  }
      }
    
    setTailleCell();

    tooLongGridW = (width < realWidth);
    tooLongGridH = (height < realHeight);
    System.out.println("tooW"+tooLongGridW);
    System.out.println("tooH"+ tooLongGridH);

    scrollBarHMode = smH;
    scrollBarVMode = smV;
    if (scrollBarHMode)
      {
	scrollBarH = new Scrollbar(Scrollbar.HORIZONTAL);
	if (tooLongGridW)
	  add("South",scrollBarH);
      }
    else
      scrollBarH = null;
    if (scrollBarVMode)
      {
	scrollBarV = new Scrollbar(Scrollbar.VERTICAL);
	if (tooLongGridH)
	  add("East",scrollBarV);
      }
    else
      scrollBarV = null;

    if (scrollBarHMode && scrollBarVMode && tooLongGridW && tooLongGridH)
      resize(width+18,height+18);
    else
      if (scrollBarHMode && tooLongGridW)
	resize(width,height+18);
      else
	if (scrollBarVMode && tooLongGridH)
	  resize(width+18,height);
	else
	  resize(width,height);

  

    if (visibleFields)
      {
	gridPanel.move(tailleCellX,tailleCellY);
	
	gridPanel.resize(realWidth-tailleCellX,realHeight-tailleCellY);
	gridPanel.setBackground(borderColor);
	
	basePanel.add(panelFieldH);
	panelFieldH.move(tailleCellX,0);
	panelFieldH.resize(realWidth-tailleCellX,tailleCellY);
    
	basePanel.add(panelFieldV);   
	panelFieldV.move(0,tailleCellY);
	panelFieldV.resize(tailleCellX,realHeight-tailleCellY);

	basePanel.add(panelTitle);
	panelTitle.move(0,0);
	panelTitle.resize(tailleCellX,tailleCellY);
	//setTitle(null);
      }
    else
      {
	
	gridPanel.resize(realWidth,realHeight);
	gridPanel.setBackground(borderColor); 
      }

    if (scrollBarHMode && tooLongGridW)
      resizeHorz();
    if (scrollBarVMode && tooLongGridH)
      resizeVert();

    basePanel.resize(width,height);
    repaint();
  }


/* --------------------------------------------------------------------------------- */
/* -                        METHODES DE CLASSE PUBLIQUES                           - */
/* --------------------------------------------------------------------------------- */

  /**
   * Renvoi la longueur de la cellule
   */
  public int getTailleCellX()
  {
    return tailleCellX;
  }


  /**
   * Renvoi la hauteur de la cellule
   */
  public int getTailleCellY()
  {
    return tailleCellY;
  }


  /**
   * Fixe la couleur de la  cellule de coord X,Y.
   * @param x Abscisse de la cellule dans la grid.
   * @param y Ordonnee de la cellule dans la grid.
   * @param c nouvelle couleur.
   */
  public void setColorAt(int x,int y,Color c)
  {
    ((Cell)(grid.elementAt(computeIndexGrid(x,y)))).setColor(c);  
  }


  /**
   * Recupere l'objet graphique contenu dans la cellule X,Y.
   * Retourne null si la cellule est vide.
   * @param x Abscisse de la cellule dans la grid.
   * @param y Ordonnee de la cellule dans la grid.
   */
  public Component getContentAt(int x,int y)
  {
    return (((Cell)(grid.elementAt(computeIndexGrid(x,y)))).getContent());
  }

  public boolean setContentAt(int x,int y,Component c)
  {
    boolean status;

    if ((x>0 && x<=nbCols) && (y>0 && y<=nbRows) && (c!=null))
      {
	status=((Cell)(grid.elementAt(computeIndexGrid(x,y)))).setContent(c);
	if (dynamicSize) 
	  // +10 car on rajoute une zone 'libre' pour pouvoir selectionner l'objet.
	  {	   
	    if (visibleFields)
	      {
		System.out.println("taille o "+c.preferredSize());
		if (realWidth-tailleCellX<((c.preferredSize().width+getBorderSize())*nbCols)) 
		  setRealWidth((c.preferredSize().width+getBorderSize()+10)*(nbCols+1));
		if (realHeight-tailleCellY<((c.preferredSize().height+borderSize)*nbRows))
		  setRealHeight((c.preferredSize().height+borderSize+10)*(nbRows+1));
	      }
	    else
	      {    
		if (realWidth<((c.preferredSize().width+getBorderSize())*nbCols)) 
		  setRealWidth((c.preferredSize().width+getBorderSize()+10)*nbCols);
		if (realHeight<((c.preferredSize().height+borderSize)*nbRows))
		  setRealHeight((c.preferredSize().height+borderSize+10)*nbRows);
	      }
	  }
	repaint();
	return status;
      }
    else
      return false;
  }


  /**
   * Indique si la cellule X,Y de la grid est vide ( i.e: n'a pas d'objet graphique affecte). 
   * Retourne faux si aucun objet n'est present.
   * @param x Abscisse de la cellule dans la grid.
   * @param y Ordonnee de la cellule dans la grid.
   */
  public boolean isEmptyContentAt(int x,int y)
  {
    if ((x>0 && x<=nbCols) && (y>0 && y<=nbRows))
      return (((Cell)(grid.elementAt(computeIndexGrid(x,y)))).isEmptyContent());
    else
      return false;
  }


 /**
   * Supprime l'objet graphique dans la cellule X,Y. 
   * Retourne faux si aucun objet n'est present.
   * @param x Abscisse de la cellule dans la grid.
   * @param y Ordonnee de la cellule dans la grid.
   */
  public boolean deleteContentAt(int x,int y)
  {
    if ((x>0 && x<=nbCols) && (y>0 && y<=nbRows))
      return (((Cell)(grid.elementAt(computeIndexGrid(x,y)))).deleteContent());
    else
      return false;
  }

  /**
   * Retourne la cellule col,row. 
   * @param col Colonne de la cellule dans la grid.
   * @param row Ligne de la cellule dans la grid.
   */
  public Cell getCellAt(int col, int row)
  {
    if ((col>0 && col<=nbCols) && (row>0 && row<=nbRows))
      return (Cell)(grid.elementAt(computeIndexGrid(col,row)));
    else
      return null;
  }


  /**
   * Affecte une cellule a la position col,row. 
   * @param col Colonne de la cellule dans la grid.
   * @param row Ligne de la cellule dans la grid.
   */
  public void setCellAt(Cell c, int col, int row)
  {
    if ((col>0 && col<=nbCols) && (row>0 && row<=nbRows) && (c!=null))
      {
	Cell displayCell = getCellAt(col,row);

	displayCell.setContent(c.getContent());
	displayCell.setColor(c.getColor());
	displayCell.setSelected(c.getSelected());
       	displayCell.setVisibleContent(c.getVisible());

	repaint();
      }
  }


  /**
   * Deplacement de l'objet graphique de la cellule Xs,Ys dans la cellule Xd,Yd. 
   * Retourne faux si echec de la copie.
   * @param xs Abscisse de la cellule source dans la grid.
   * @param ys Ordonnee de la cellule source dans la grid.
   * @param xd Abscisse de la cellule destination dans la grid.
   * @param yd Ordonnee de la cellule destination dans la grid.
   */
  public boolean moveCell(int xs,int ys,int xd,int yd)
  {
    if ((xs>0 && xs<=nbCols) && (ys>0 && ys<=nbRows) && (xd>0 && xd<=nbCols) && (yd>0 && yd<=nbRows) && (xs!=xd) && (ys!=yd))
      {
	Cell c = getCellAt(xs,ys);
	Cell newCell = new Cell(c.getContent(),c.getColor(),c.getSelected(),c.getVisible());
	deleteContentAt(xs,ys);
	setCellAt(newCell,xd,yd);

	return true;
      }
    return false;
  }

  
  /**
   * Deplacement de l'objet graphique de la cellule Xs,Ys dans la cellule Xd,Yd. 
   * Retourne faux si echec de la copie.
   * @param xs Abscisse de la cellule source dans la grid.
   * @param ys Ordonnee de la cellule source dans la grid.
   * @param xd Abscisse de la cellule destination dans la grid.
   * @param yd Ordonnee de la cellule destination dans la grid.
   */
  public boolean moveContent(int xs,int ys,int xd,int yd)
  {
     Component c;

    c=getContentAt(xs,ys);
    if (c==null)
      return false;
    if (setContentAt(xd,yd,c))
	{
	  deleteContentAt(xs,ys);
	  return true;
	}
    return false;
  }


  /**
   * Retourne le nombre de colonnes de la grid.
   */
  public int getCols()
  {
    return nbCols;
  }


  /**
   * Retourne le nombre de lignes de la grid.
   */
  public int getRows()
  {
    return nbRows;
  }


  /**
   * Retourne la taille de la bordure en pixels.
   */
  public int getBorderSize()
  {
    return borderSize;
  }


  /**
   * Fixe la largeur de la grid en pixels.
   * @param w nouvelle largeur.
   */
  public void setWidth(int w)
  {
    if (w>=MIN_WIDTH)
      {
	width=w;
	resize(width,height);
	repaint();
      }
  }


  /**
   * Retourne la largeur de la grid en pixels.
   */
  public int getWidth()
  {
    return width;
  }


  /**
   * Fixe la hauteur de la grid en pixels.
   * @param h nouvelle valeur.
   */
  public void setHeight(int h)
  {
    if (h>=MIN_HEIGHT)
      {
	height=h;
	resize(width,height);
	repaint();
      }
  }


  /**
   * Retourne la hauteur de la grid en pixels.
   */
  public int getHeight()
  {
    return height;
  }

  /**
   * Fixe la largeur de la grid en pixels.
   * @param w nouvelle largeur.
   */
  public void setRealWidth(int w)
  { 

    boolean oldTooLongGridW;
    int tailleX;


    if (w>=MIN_WIDTH)
      {
	if (visibleFields)
	  tailleX=tailleCellX;
	else
	  tailleX=0;
	oldTooLongGridW = (width  < realWidth);

	realWidth=w;

	setTailleCell();

	tooLongGridW = (width < realWidth);


	if (!oldTooLongGridW && tooLongGridW)
	  {
	  add("South",scrollBarH);
	  if (tooLongGridH)
	    resize(width+18,height+18);
	  else
	    resize(width,height+18);
	  }

        if (oldTooLongGridW && !tooLongGridW)
	  {
 	  remove(scrollBarH);
	  if (tooLongGridH)
	    resize(width+18,height);
	  else
	    resize(width,height);
	  }

	if (visibleFields)
	  {
	    gridPanel.move(tailleCellX,tailleCellY);
	    panelFieldH.move(tailleCellX,0);
	    panelFieldH.resize(realWidth-tailleCellX,tailleCellY);

	    panelFieldV.resize(tailleCellX,realHeight-tailleCellY);
	    panelFieldV.move(0,tailleCellY);

	    panelTitle.resize(tailleCellX,tailleCellY);
	    gridPanel.resize(realWidth-tailleCellX,realHeight-tailleCellY);  
	  }
	else
	  gridPanel.resize(realWidth,realHeight);

	repaint();
      }
  }


  /**
   * Retourne la largeur de la grid dans sa totalite en pixels.
   */
  public int getRealWidth()
  {
    return realWidth;
  }


  /**
   * Fixe la hauteur de la grid dans sa totalite en pixels.
   * @param h nouvelle valeur.
   */
  public void setRealHeight(int h)
  {

    boolean oldTooLongGridH;
    int tailleY;

    if (visibleFields)
      tailleY=tailleCellY;
    else
      tailleY=0;

    if (h>=MIN_HEIGHT)
      {

	oldTooLongGridH = (height < realHeight);	

	realHeight=h;

	setTailleCell();

	tooLongGridH= (height < realHeight);

	if (!oldTooLongGridH && tooLongGridH)
	  {
	  add("East",scrollBarV);
	  if (tooLongGridW)
	    resize(width+18,height+18);
	  else
	    resize(width+18,height);
	  }


	if (oldTooLongGridH && !tooLongGridH)
	  {
	  remove(scrollBarV);
	  if (tooLongGridW)
	    resize(width+18,height);
	  else
	    resize(width,height);
	  }

	if (visibleFields)
	  {
	    gridPanel.move(tailleCellX,tailleCellY);
	    
	    panelFieldH.move(tailleCellX,0);
	    panelFieldH.resize(realWidth-tailleCellX,tailleCellY);
	    
	    panelFieldV.resize(tailleCellX,realHeight-tailleCellY);
	    panelFieldV.move(0,tailleCellY);
	    
	    panelTitle.resize(tailleCellX,tailleCellY);
	    gridPanel.resize(realWidth-tailleCellX,realHeight-tailleCellY);
	  
	  }	
	else
	  gridPanel.resize(realWidth,realHeight);

	repaint();
      }
  }


  /**
   * Retourne la hauteur de la grid dans sa totalite en pixels.
   */
  public int getRealHeight()
  {
    return realHeight;
  }


  /**
   * Permet de redimensionner automatiquement la Grid en fonction de son contenu.
   * @param status Booleen activant ou non le redimensionnement automatique
   */
  public void setDynamicSize(boolean status)
  {
    dynamicSize=status;
  }


  /**
   * Retourne un booleen indiquant si la Grid est redimensionnable automatiquement en fonction de son contenu.
   */
  public boolean getDynamicSize()
  {
    return dynamicSize;
  }


  /**
   * Permet de de rendre valide ou non le mode interactif (selections souris).
   * @param status Booleen activant ou non le mode interactif
   */
  public void setInteractive(boolean status)
  {
    interactive=status;
  }


  /**
   * Retourne un booleen indiquant si l'utilisateur peut faire des selections a la souris ou non.
   */
  public boolean getInteractive()
  {
    return interactive;
  }


  /**
   * Affecte un titre de la grid.
   * @param titre String representant le titre de la Grid
   */
  public void setTitle(String titre)
  {
    int taille;
    if (titre!=null)
      {
	if (title==null)
	  title=new String(titre);
	else
	  title=titre;
	if (dynamicSize)
	  {
	    taille=(((Field)(grid.elementAt(0))).getFontMetrics(((Field)(grid.elementAt(0))).getFont())).stringWidth(titre);
	    if (tailleCellX<taille) 
	      setRealWidth(taille*(nbCols+1));
	  }
	((Field)(grid.elementAt(0))).setTextField(titre);
      }
  }


  /**
   * Retourne le titre de la grid.
   * null si pas de titre
   */
  public String getTitle()
  {
    return title;
  }


  /**
   * Fixe la valeur d'un champ vertical.
   * @param f numero du champ.
   * @param v nouvelle valeur du champ.
   */
  public void setVerticalField(int f,String v)
  {
    int taille;

    if (dynamicSize)
     {
       taille=(((Field)(grid.elementAt(0))).getFontMetrics(((Field)(grid.elementAt(0))).getFont())).stringWidth(v);
       if (tailleCellX<taille) 
	 setRealWidth(taille*(nbCols+1));
     }   
    ((Field)(grid.elementAt(f*(nbCols+1)))).setTextField(v);
  }


  /**
   * Recupere la valeur d'un champ vertical.
   * Retourne une String.
   * @param f numero du champ.
   */
  public String getVerticalField(int f)
  {
    return (((Field)(grid.elementAt(f*(nbCols+1)))).getTextField());
  }


  /**
   * Fixe la valeur d'un champ horizontal.
   * @param f numero du champ.
   * @param v nouvelle valeur du champ.
   */
  public void setHorizontalField(int f,String v)
  {
    int taille;

    if (dynamicSize)
      {
       taille=(((Field)(grid.elementAt(0))).getFontMetrics(((Field)(grid.elementAt(0))).getFont())).stringWidth(v);
       if (tailleCellX<taille) 
	 setRealWidth(taille*(nbCols+1));
      }   
    ((Field)(grid.elementAt(f))).setTextField(v);
  }


  /**
   * Recupere la valeur d'un champ horizontal.
   * Retourne une String.
   * @param f numero du champ.
   */
  public String getHorizontalField(int f)
  {
    return (((Field)(grid.elementAt(f*(nbCols+1)))).getTextField());
  }


  /**
   * Retourne une liste de points (classe Point) correspondant aux numeros X,Y des cellules selectionnees
   */
  public Vector getCellsSelected()
  {
    Vector List  = new Vector();
    Point  point;
    int x;
    int y;

    for (int cmpt=0; cmpt<cellsSelected.size(); cmpt++)
      {
	x = computeXCoord(((Integer)cellsSelected.elementAt(cmpt)).intValue());
	y = computeYCoord(((Integer)cellsSelected.elementAt(cmpt)).intValue());
	point = new Point(x,y);
	List.addElement(point);
      }

    return List;
  }


  /**
   * Ajoute la cellule col,row dans la liste des cellules selectionnees.
   * @param col Colonne de la cellule selectionnee.
   * @param row Ligne de la cellule selectionnee.
   */
  public boolean addCellSelected(int col,int row)
  {
    if ((col>0 && col<=nbCols) && (row>0 && row<=nbRows))
      {
	Integer i = new Integer(computeIndexGrid(col,row));
	if (!cellsSelected.contains(i))
	  cellsSelected.addElement(i);
	return true;
      }
    else
      return false;
  }


  /**
   * Ajoute les cellules comprises dans le rectangle col1,row1 et col2,row2 dans la liste des cellules selectionnees.
   * @param col1 Colonne de la premiere cellule selectionnee.
   * @param row1 Ligne de la premiere cellule selectionnee.
   * @param col2 Colonne de la deuxieme cellule selectionnee.
   * @param row2 Ligne de la deuxieme cellule selectionnee.
   */
  public boolean addCellSelected(int col1, int row1, int col2, int row2)
  { 
    if ((col1>0 && col1<=nbCols) && (row1>0 && row1<=nbRows) && (col2>0 && col2<=nbCols) && (row2>0 && row2<=nbRows))
      {
	firstPosX  = col1;
	firstPosY  = row1;
	secondPosX = col2;
	secondPosY = row2;
	boolean firstSelect = ((Cell)(grid.elementAt(computeIndexGrid(firstPosX,firstPosY)))).selected;
	int beginX = 0;
	int beginY = 0;
	int endX   = 0;
	int endY   = 0;
	if (firstPosX<=secondPosX && firstPosY<=secondPosY)
	  {
	    beginX = firstPosX;
	    beginY = firstPosY;
	    endX   = secondPosX;
	    endY   = secondPosY;
	  }
	if (firstPosX>=secondPosX && firstPosY>=secondPosY)
	  {
	    beginX = secondPosX;
	    beginY = secondPosY;
	    endX   = firstPosX;
	    endY   = firstPosY;
	  }
	if (firstPosX<=secondPosX && firstPosY>=secondPosY)
	  {
	    beginX = firstPosX;
	    beginY = secondPosY;
	    endX   = secondPosX;
	    endY   = firstPosY;
	  }
	if (firstPosX>=secondPosX && firstPosY<=secondPosY)
	  {
	    beginX = secondPosX;
	    beginY = firstPosY;
	    endX   = firstPosX;
	    endY   = secondPosY;
	  }
	for (int cmpt1=beginY; cmpt1<=endY; cmpt1++)
	  for (int cmpt2=beginX; cmpt2<=endX; cmpt2++)
	    {
	      addCellSelected(cmpt2,cmpt1);
	      ((Cell)(grid.elementAt(computeIndexGrid(cmpt2,cmpt1)))).setSelected(true);
	    } 
	return true;
      }
    else 
      return false;
  }
    
    
    /**
     * Deselectionne toutes les cellules.
     */
  public void deselectAllCells()
  {
    if (cellsSelected.size()!=0)
      {
	removeCellsSelected();
	for (int cmpt1=1; cmpt1<=nbRows; cmpt1++)
	  for (int cmpt2=1; cmpt2<=nbCols; cmpt2++)
	    ((Cell)(grid.elementAt(computeIndexGrid(cmpt2,cmpt1)))).setSelected(false);
      }
  }


  /**
   * Deselectionne la cellule a la colonne col et la ligne row.
   * @param col Colonne de la cellule a deselectionner.
   * @param row Ligne de la cellule a deselectionner.
   */
  public void deselectCellAt(int col,int row)
  {
    if ((col>0 && col<=nbCols) && (row>0 && row<=nbRows))
      {
	Integer i = new Integer(computeIndexGrid(col,row));
	
	if (((Cell)(grid.elementAt(computeIndexGrid(col,row)))).selected)
	  {
	    cellsSelected.removeElementAt(cellsSelected.indexOf(i));
	    ((Cell)(grid.elementAt(computeIndexGrid(col,row)))).setSelected(false);
	  }
      }
  }


  /**
   * Retourne un booleen indiquant si des cellules ont ete selectionnees ou non.
   */
  public boolean isEmptyCellsSelected()
  {
    return cellsSelected.isEmpty();
  }


  /**
   * Retourne le nombre de cellules selectionnees.
   */
  public int cellsSelectedSize()
  {
    return cellsSelected.size();
  }


  /**
   * Renvoi l'abscisse de la cellule qui a recu le dernier evenement souris 
   */
  public int getCurrentCellPosX()
  {
    return currentCellPosX;
  }


  /**
   * Renvoi l'ordonnee de la cellule qui a recu le dernier evenement souris 
   */
  public int getCurrentCellPosY()
  {
    return currentCellPosY;
  }


  /**
   * methode paint
   */
  public void paint(Graphics g) 
  {
  
    if (scrollBarHMode && scrollBarVMode && tooLongGridW && tooLongGridH)
      resize(width+18,height+18);
    else
      if (scrollBarHMode && tooLongGridW)
	resize(width,height+18);
      else
	if (scrollBarVMode && tooLongGridH)
	  resize(width+18,height);
	else
	  resize(width,height);

    if (basePanel!=null)
      basePanel.resize(width,height);

    if (gridPanel!=null)
      if (visibleFields)
	gridPanel.resize(realWidth-tailleCellX,realHeight-tailleCellY);
      else
	gridPanel.resize(realWidth,realHeight);

    g.setColor(Color.white);

    if (scrollBarHMode && tooLongGridW)
      resizeHorz();
    if (scrollBarVMode && tooLongGridH)
      resizeVert();

    if (visibleFields)
      {
	panelFieldH.resize(realWidth-tailleCellX,tailleCellY);
	panelFieldV.resize(tailleCellX,realHeight-tailleCellY);
	panelTitle.resize(tailleCellX,tailleCellY);
      }
  }


/* --------------------------------------------------------------------------------- */
/* -                        METHODES DE CLASSE PRIVEES                             - */
/* --------------------------------------------------------------------------------- */

  // Renvoi l'abscisse de la cellule correspondante a l'index du vecteur grid passe en parametre
  int computeXCoord(int index)
  {
    return (int)(index % (nbCols+1));
  }


  // Renvoi l'ordonnee de la cellule correspondante a l'index du vecteur grid passe en parametre
  int computeYCoord(int index)
  {
    return (int)(index / (nbCols+1));
  }

  // Transforme l'abscisse de la position pixels de la souris en abscisse du numero de cellule
  int computeMouseX(int x)
  {
    int i,tailleCell,border,scroll;


  
    if (visibleBorder)
      border=getBorderSize();
    else 
      border=0;
//     if (scrollBarH!= null)
//       scroll=scrollBarH.bounds().height;
//     else 
//       scroll=0;
    if (visibleFields)
      {
      tailleCell=tailleCellX;
      if (x<tailleCell)
	return 0;
      for (i=1;i<=nbCols+1;i++)
	  if ((x+tScrollBarX<(tailleCell+((tailleCell+border))*(i-1))) && (x<=width))
	      return (i-1);
      }
    else
      {
	tailleCell=tailleCellX;
	for (i=1;i<=nbCols;i++)
	    if ((x+tScrollBarX<((tailleCell+border))*i) && (x<=width)) 
		return i;	   
      }
    return -1;
  }


  // Transforme l'ordonnee de la position pixels de la souris en ordonnee du numero de cellule
  int computeMouseY(int y)
  {
    int i,tailleCell,border,scroll ;

    
    if (visibleBorder)
      border=getBorderSize();
    else 
      border=0;
    //    if (scrollBarH!= null)
    //      scroll=scrollBarH.bounds().height;
      //    else 
      //      scroll=0;
    if (visibleFields)
      {
      tailleCell=tailleCellY;
      if (y<tailleCell)
	return 0;
      for (i=1;i<=nbRows+1;i++)
	  if ((y+tScrollBarY<(tailleCell+((tailleCell+border))*(i-1))) && (y<=height))
	      return (i-1);
      }
    else
      {
	tailleCell=tailleCellY;
	for (i=1;i<=nbRows;i++)
	    if ((y+tScrollBarY<((tailleCell+border))*i) && (y<=height)) 
		return i;
      }
    return -1;
  }    


  // Determine la taille en X et en Y d'une cellule
  void setTailleCell()
  {
    int tailleCell,border;
    // int scroll;

    if (visibleBorder)
      border=getBorderSize();
    else 
      border=0;
    //    scroll=scrollBarV.bounds().width;
    if (visibleFields)
      {
 	tailleCellX=(getRealWidth()-getCols()*border)/(getCols()+1);
 	tailleCellY=(getRealHeight()-getRows()*border)/(getRows()+1);
      }
     else
       {
    tailleCellX=(getRealWidth()-getCols()*border)/(getCols());
    tailleCellY=(getRealHeight()-getRows()*border)/(getRows());
     }
  }


  // renvoi l'index de la grid pour une abscisse et une ordonnee d'une cellule
  int computeIndexGrid(int x, int y)
  {
    return x + ((nbCols + 1) * y);
  }


  // Met a jour la variable de position x de la cellule ayant recu le dernier evenement souris
  void setCurrentCellPosX(int x)
  {
    //if (x>=0)
      currentCellPosX = x;
  }


  // Met a jour la variable de position y de la cellule ayant recu le dernier evenement souris
  void setCurrentCellPosY(int y)
  {
    //if (y>=0)
      currentCellPosY = y;
  }


  // Efface le contenu du vecteur contenant les index des cellules selectionnees
  void removeCellsSelected()
  {
    cellsSelected.removeAllElements();
  }


  // Efface l'index de la cellule col,row dans le vecteur d'index de cellules selectionnees
  void removeCellSelected(int col,int row)
  {
    Integer i = new Integer(computeIndexGrid(col,row));

    if (((Cell)(grid.elementAt(computeIndexGrid(col,row)))).selected)
      cellsSelected.removeElementAt(cellsSelected.indexOf(i));
  }


  // Permet de retailler la barre de deplacement de la scrollbar horizontale
  void resizeHorz() 
  {
    int basePanelWidth,tailleCell;

    basePanelWidth = width;
    if (visibleFields)
      tailleCell=tailleCellX;
    else
      tailleCell=0;
    if ((tScrollBarX + basePanelWidth) > gridPanel.size().width+tailleCell) 
      {
	int newtx = gridPanel.size().width - basePanelWidth;
	if (newtx < 0) 
	  newtx = 0;
	tScrollBarX = newtx;
      }
    scrollBarH.setValues(tScrollBarX,(int)(basePanelWidth * 0.9),0,gridPanel.size().width - basePanelWidth+tailleCell);
    scrollBarH.setPageIncrement((int)(basePanelWidth * 0.9));
    scrollBarH.setLineIncrement((int)(gridPanel.size().width / (2 * nbCols))); 
    return;
  }


  // Permet de retailler la barre de deplacement de la scrollbar verticale
  void resizeVert() 
  {
    int basePanelHeight,tailleCell;

    basePanelHeight = height;
    if (visibleFields)
      tailleCell=tailleCellY;
    else
      tailleCell=0;

    if ((tScrollBarY + basePanelHeight) > gridPanel.size().height+tailleCell) 
      {
	int newtx = gridPanel.size().height - basePanelHeight;
	if (newtx < 0) 
	  newtx = 0;
	tScrollBarY = newtx;
      }
    scrollBarV.setValues(tScrollBarY,(int)(basePanelHeight * 0.9),0,gridPanel.size().height - basePanelHeight+tailleCell);
    scrollBarV.setPageIncrement((int)(basePanelHeight * 0.9));
    scrollBarV.setLineIncrement((int)(gridPanel.size().height / (2 * nbRows))); 
    return;
  }
  

/* --------------------------------------------------------------------------------- */
/* -                             GESTION DES EVENEMENTS                            - */
/* --------------------------------------------------------------------------------- */

  /** 
   * Gestion des evenenements 
   * @param evt Evenement survenu
   */
  public boolean handleEvent(Event evt) 
  { 
    switch (evt.id) 
      {
      case Event.SCROLL_LINE_UP:
      case Event.SCROLL_LINE_DOWN:
      case Event.SCROLL_PAGE_UP:
      case Event.SCROLL_PAGE_DOWN:
      case Event.SCROLL_ABSOLUTE:
	if (evt.target == scrollBarV) 
	  {
	    tScrollBarY = ((Integer)evt.arg).intValue();

	    if (visibleFields)
	      {
		gridPanel.move(tailleCellX-tScrollBarX,tailleCellY-tScrollBarY);
		panelFieldV.move(0,tailleCellY-tScrollBarY);
	      }
	    else
	      gridPanel.move(-tScrollBarX,-tScrollBarY);

	    repaint();
	  }
	if (evt.target == scrollBarH) 
	  {
	    tScrollBarX = ((Integer)evt.arg).intValue();

	    if (visibleFields)
	      {
		gridPanel.move(tailleCellX-tScrollBarX,tailleCellY-tScrollBarY);
		panelFieldH.move(tailleCellX-tScrollBarX,0);
	      }
	    else
	      gridPanel.move(-tScrollBarX,-tScrollBarY);

	    repaint();
	  }
      }
    return super.handleEvent(evt);
  }


  /**
  /* Methode evenementielle lorsque un click souris est detecte sur la Grid.
   * @param event Evenenement survenu.
   * @param x Position en abscisse de la souris.
   * @param y Position en ordonnee de la souris.
   */
  public boolean mouseDown(Event event, int x, int y) 
  {
    if (interactive)
      {
	if (!event.controlDown() && !event.shiftDown() && cellsSelected.size()!=0)
	  deselectAllCells();
	if (currentCellPosX==0 && currentCellPosY==0)
	  {
	    boolean sel = !((Cell)(grid.elementAt(computeIndexGrid(1,1)))).selected;
	    for (int cmpt1=1; cmpt1<=nbRows; cmpt1++)
	      for (int cmpt2=1; cmpt2<=nbCols; cmpt2++)
		{
		  if (sel)
		    addCellSelected(cmpt2,cmpt1);
		  else
		    removeCellSelected(cmpt2,cmpt1);
		  ((Cell)(grid.elementAt(computeIndexGrid(cmpt2,cmpt1)))).setSelected(sel);
		}
	  }	
	else 
	  if (currentCellPosX==0 && currentCellPosY!=0)
	    {
	      boolean sel = !((Cell)(grid.elementAt(computeIndexGrid(1,currentCellPosY)))).selected; 
	      for (int cmpt=1; cmpt<=nbCols; cmpt++)
		{
		  if (sel)
		    addCellSelected(cmpt,currentCellPosY);
		  else
		    removeCellSelected(cmpt,currentCellPosY);
		  ((Cell)(grid.elementAt(computeIndexGrid(currentCellPosX+cmpt,currentCellPosY)))).setSelected(sel);
		}
	    }
	  else 
	    if (currentCellPosX!=0 && currentCellPosY==0)
	      {
		boolean sel = !((Cell)(grid.elementAt(computeIndexGrid(currentCellPosX,1)))).selected;
		for (int cmpt=1; cmpt<=nbRows; cmpt++)
		  {
		    if (sel)
		      addCellSelected(currentCellPosX,cmpt);
		    else
		      removeCellSelected(currentCellPosX,cmpt);
		    ((Cell)(grid.elementAt(computeIndexGrid(currentCellPosX,currentCellPosY+cmpt)))).setSelected(sel);
		  }
	      }	
	    else
	      if (!event.shiftDown())
		{
		  firstPosX = currentCellPosX;
		  firstPosY = currentCellPosY;
		  boolean sel = ((Cell)(grid.elementAt(computeIndexGrid(currentCellPosX,currentCellPosY)))).selected;
		  if (!sel)
		    addCellSelected(currentCellPosX,currentCellPosY);
		  else
		    removeCellSelected(currentCellPosX,currentCellPosY);
		  ((Cell)(grid.elementAt(computeIndexGrid(currentCellPosX,currentCellPosY)))).setSelected(!sel);
		}
	      else
		{
		  secondPosX = currentCellPosX;
		  secondPosY = currentCellPosY;
		  boolean firstSelect = ((Cell)(grid.elementAt(computeIndexGrid(firstPosX,firstPosY)))).selected;
		  int beginX = 0;
		  int beginY = 0;
		  int endX   = 0;
		  int endY   = 0;
		  if (firstPosX<=secondPosX && firstPosY<=secondPosY)
		    {
		      beginX = firstPosX;
		      beginY = firstPosY;
		      endX   = secondPosX;
		      endY   = secondPosY;
		    }
		  if (firstPosX>=secondPosX && firstPosY>=secondPosY)
		    {
		      beginX = secondPosX;
		      beginY = secondPosY;
		      endX   = firstPosX;
		      endY   = firstPosY;
		    }
		  if (firstPosX<=secondPosX && firstPosY>=secondPosY)
		    {
		      beginX = firstPosX;
		      beginY = secondPosY;
		      endX   = secondPosX;
		      endY   = firstPosY;
		    }
		  if (firstPosX>=secondPosX && firstPosY<=secondPosY)
		    {
		      beginX = secondPosX;
		      beginY = firstPosY;
		      endX   = firstPosX;
		      endY   = secondPosY;
		    }
		  for (int cmpt1=beginY; cmpt1<=endY; cmpt1++)
		    for (int cmpt2=beginX; cmpt2<=endX; cmpt2++)
		      {
			if (firstSelect)
			  addCellSelected(cmpt2,cmpt1);
			else
			  removeCellSelected(cmpt2,cmpt1);
			((Cell)(grid.elementAt(computeIndexGrid(cmpt2,cmpt1)))).setSelected(firstSelect);
		      }
		}
	repaint();
      }
    return false;
  }
    

  /**
   * gestion de l'evenement Drag 
   * @param e Evenement
   * @param x Position x de la souris (pixels)
   * @param y Position y de la souris (pixels)
   */
  public boolean mouseDrag(Event e, int x,int y)
  {

   setCurrentCellPosX(computeMouseX(x));
   setCurrentCellPosY(computeMouseY(y));
   return false;
  }


  /**
   * gestion de l'evenement Up
   * @param e Evenement
   * @param x Position x de la souris (pixels)
   * @param y Position y de la souris (pixels)
   */
  public boolean mouseUp(Event e, int x,int y)
  {

   setCurrentCellPosX(computeMouseX(x));
   setCurrentCellPosY(computeMouseY(y));
   return false;
  }


  /**
   * gestion de l'evenement Enter
   * @param e Evenement
   * @param x Position x de la souris (pixels)
   * @param y Position y de la souris (pixels)
   */
  public boolean mouseEnter(Event event, int x, int y) 
  { 
    setCurrentCellPosX(computeMouseX(x));
    setCurrentCellPosY(computeMouseY(y));

    return false;
  }
  
}
  
  
  /* --------------------------------------------------------------------------------- */
  /* -                                 Classe Field                                  - */
  /* --------------------------------------------------------------------------------- */
  /* - Description :                                                                 - */
  /* -    Permet de personnaliser le paint() herite de Canvas                        - */
  /* --------------------------------------------------------------------------------- */

  class Field extends Panel
  {
    String  text;
    Color   colFond;
    Color   colText;
    
    /* --------------------------------------------------------------------------------- */
    /* -                                 CONSTRUCTEURS                                 - */
    /* --------------------------------------------------------------------------------- */
    
   public Field(String t, Color cf, Color ct)
    {
      super();
      colFond = cf;
      colText = ct;
      text = new String(t);
      setBackground(colFond);
    }


/* --------------------------------------------------------------------------------- */
/* -                        METHODES DE CLASSE PUBLIQUES                           - */
/* --------------------------------------------------------------------------------- */
  
  /**
   * Fixe la valeur du champ text d'une instance de Field
   * @param v nouvelle valeur
   */
  public void setTextField(String v)
  {
    text=v;
    repaint();
  }


  /**
   * Retourne la valeur du champ text d'une instance de Field 
   */
  public String  getTextField()
  {
    System.out.println("field "+text);
    return text;
  }


  /**
   * Fixe la couleur de fond du champ d'une instance de Field
   * @param c nouvelle couleur
   */
  public void setBGColor(Color c)
  {
    colFond = c;
    setBackground(colFond);
    repaint();
  }


  /**
   * Retourne  la couleur de fond du champ d'une instance de Field 
   */
  public Color getBGColor()
  {
    return colFond;
  }


    /**
     * Fixe la couleur du champ text d'une instance de Field
     * @param c nouvelle couleur
     */
  public void setTextColor(Color c)
  {
    colText = c;
    repaint();
  }


  /**
   * Retourne la couleur du champ text d'une instance de Field 
   */
  public Color getTextColor()
  {
    return colText;
  }

    /**
     * Inverse le contenu de deux Fields
     * @param xs abscisse de la cellule source
     * @param ys ordonnee de la cellule source
     * @param xd abscisse de la cellule destination
     * @param yd ordonnee de la cellule destination
     */
//     public void inverseFields(int xs,int ys,int xd,int yd)
//     {
//       Field s= ((Field)(grid.elementAt(computeIndexGrid(xs,ys)))).getContent();
//       Field d= ((Field)(grid.elementAt(computeIndexGrid(xd,yd)))).getContent();

//       Field sn= new Field(s.text,s.colFond,s.colText);
//       Field dn= new Field(d.text,d.colFond,d.colText);
      
      

  /**
   * Methode paint
   */
  public void paint(Graphics g)
  { 
    g.setColor(colText);
    g.drawString(text, (size().width - g.getFontMetrics().stringWidth(text))/2,(size().height + g.getFontMetrics().getHeight()/2)/2);
  }

}


/* --------------------------------------------------------------------------------- */
/* -                                 Classe Cell                                   - */
/* --------------------------------------------------------------------------------- */
/* - Description :                                                                 - */
/* -    Caracterise l'entite elementaire cellule, extension de la classe 'Panel'   - */
/* -    pouvant contenir un objet de type graphique generique 'Component' avec des - */
/* -    attributs personnels tels que la couleur de fond, sa longueur, hauteur et  - */
/* -    divers flag booleen decrivant l'etat de celle ci.                          - */
/* --------------------------------------------------------------------------------- */

class Cell extends Panel
{

  Component content;     // Objet graphique place dans la cellule

  Color     color;       // Couleur de fond de la cellule
  boolean   selected;    // 'true' si la cellule est selectionne
  boolean   visible;     // 'true' si le 'content' est visible 



/* --------------------------------------------------------------------------------- */
/* -                                 CONSTRUCTEURS                                 - */
/* --------------------------------------------------------------------------------- */

  
  /**
   * Creer une cellule avec les valeurs par defaut.
   */
  public Cell()       // Constructeur par defaut
  {
    content     = null; 
    color       = Color.white;  
    selected    = false;
    visible     = true;

    setBackground(color);
    repaint();
  }

  
  /**
   * Creer une cellule avec les parametres utilisateur.
   * @param c  L'objet graphique qui est attache a cette cellule.
   * @param co Couleur de fond de la cellule.
   * @param s  Booleen indiquant si la cellule est selectionne par defaut ou non.
   * @param v  Booleen indiquant si l'objet graphique attache a la cellule est visible ou non.
   */
  public Cell(Component c, Color co, boolean s, boolean v)
  {
    content = c;
    if (content!=null)
      add(content);

    color = co;
   
    if (s)
      {
	color = color.darker();
	selected = true;
      }
    else
      selected = false;
   
    visible = v;
    if (content!=null)
      {
	if (visible)
	    content.show();
	else
	    content.hide();
      }

    setBackground(color);
    repaint();
  }


  /**
   * Creer une cellule avec les parametres par defaut et utilisateur.
   * @param c L'objet graphique qui est attache a cette cellule.
   * @param co Couleur de fond de la cellule.
   */
  public Cell(Component c, Color co)
  {
    content = c;
    if (content!=null)
      {
	content.show();
	add(content);
      }
    color = co;
    selected    = false;
    visible     = true;

    setBackground(color);
    repaint();
  }


/* --------------------------------------------------------------------------------- */
/* -                        METHODES DE CLASSE PUBLIQUES                           - */
/* --------------------------------------------------------------------------------- */
  
  /**
   * Indique si la cellule est vide
   */
  public boolean isEmptyContent()
  {
    if (content==null)
      return true;
    else
      return false;
  }
  
  
  /**
   * Met l'objet graphique dans la cellule. 
   * Retourne faux si un objet est deja present
   *  @param c Objet graphique attache a la cellule
   */
  public boolean setContent(Component c)
  {
    if (isEmptyContent())
      {
	content=c;
	add(content);
	validate();
	return true;
      }
    else
      return false;
  }
  
  
  /**
   *  Retourne l'objet ou null si il n'y en a pas.
   */
  public Component getContent()
  {
    return content;
  }


  /**
   * Supprime l'objet graphique present dans la cellule.
   * Retourne faux si aucun objet ne s'y trouver.
   */
  public boolean deleteContent()
  {
    if (isEmptyContent()) 
      return false;
    else
      {
	remove(content);
	content=null;
	return true;
      }
  }  

  
  /**
   * Fixe la couleur de la cellule
   * @param c Couleur de fond de la cellule.
   */
  public void setColor(Color c)
    {
      color=c;
      setBackground(color);
    }

  
  /**
   * Retourne la valeur de la couleur courante de la cellule.
   */
  public Color getColor()
    {
      return color;
    }

  
  /**
   * Selection ou deselection d'une cellule suivant le status.
   * @param status Booleen indiquant si le bouton doit etre selectionne ou non.
   */
  public void setSelected(boolean status)
  {  
    boolean oldSelected = selected;
    selected = status;
    if (selected!=oldSelected)
      {
	if (selected)
	  color=color.darker();
	else
	  color=color.brighter();
	setBackground(color);
	repaint();
      }
    }


  /**
   * Indique si la cellule est selectionee.
   */
  public boolean getSelected()
  {
    return selected;
  }

  
  /**
   * Indique si la cellule est visible.
   */
  public boolean isVisibleContent()
  {
    return visible;
  }


  /**
   * Rend visible ou invisible l'objet suivant la valeur de status.
   * @param status Booleen indiquant si l'objet graphique attache a la cellule doit etre visible ou non.
   */
  public void setVisibleContent(boolean status)
  {
    if (visible!=status)
      {
	visible = status;
	if (visible)
	  {
	    content.show();
	    repaint();
	  }
	else
	  {
	    content.hide();
	    repaint();
	  }
      }
  }

  
  /* 
   * Renvoi le booleen indiquant si le contenu doit etre visible ou non
   */
  public boolean getVisible()
  {
    return visible;
  }


  /**
   * Methode paint
   */
  public void paint(Graphics g)
  {
    if (content!=null)
      content.move((size().width-content.bounds().width)/2,(size().height-content.bounds().height)/2);
  }

}

