// Module PI : Peida Interactive     PIScDrawWdg
// Gestionnaire Drawer-2D  E.Aubourg, R. Ansari  96-98
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include "sopnamsp.h"
#include "machdefs.h"
#include <math.h>
#include <iostream>

#include "piscdrawwdg.h"
#include "pidrwtools.h"
#include "piaxes.h"
#include "piaxestools.h"

#define PETIT_DBLE 1.e-100
#define PREC_DBLE  1.e-16


//++
// Class	PIScDrawWdg
// Lib		PI
// include	piscdrawwdg.h
//
//   	Classe pour la l'affichage et la manipulation d'un ensemble
//	de *Drawer* avec la gestion de zoom (agrandissement).
//	* Bouton-1 : Envoie le message "PIMsg_Active" et affiche
//	les coordonnées courantes (User-Coordinates)
//	* Bouton-2 : Permet de définir un rectangle pour le zoom.
//	* Bouton-3 : Permet de définir un rectangle pour le texte info.
//
//	Gestion du clavier :
//	* <Alt>O : Active/Affiche les  contrôles de paramètres spécifiques 
//	(Par défaut, action identique à <Alt>G)
//	* <Alt>G : Affichage de la fenêtre de changement des attributs graphiques
//	* <Alt>D : Affichage du menu de manipulation des traceurs (drawers)
//	* <Alt>R : Rafraîchit l'affichage.
//	* <Alt>M : Active/Désactive l'affichage d'une réticule de mesure (Bouton-1)
//	* <Alt>V : Copier/*Coller* Ajout du texte du buffer copier/coller
//	sur l'objet à la position courante.
//	* <Alt>I : Affiche et met a jour la fenetre Texte-Info .
//	* <Alt>Z : Supprime les élément graphiques ajoutés au dessin.
//	* <Alt>E : Supprime le dernier élément graphique ajouté.
//      * <Alt>P : fenetre des options de drawing des contours 
//--
//++
// Links	Parents
// PIBaseWdg
//--
//++
// Links	Voir aussi
// PIDrawer
//--

static inline void dbl_swap(double& a, double& b) { double tmp = a; a = b; b = tmp;  } 

//++
// Titre	Constructeurs, méthodes
//	Seule les méthodes les plus usuelles sont décrites ici. Se reporter
//	au fichier .h pour la liste complete des méthodes
//--
//++
//  PIScDrawWdg(PIContainerGen *par, const char *nom, int sx=100, int sy=100, int px=0, int py=0)
//	Constructeur. Contient uniquement le traceur de base, responsable du tracé
//	des axes et des éléments ajoutés (textes, ...)
// long  kind()
//	Renvoie le type ("=PIScDrawWdg::ClassId")
// void SetLimits(double xmin, double xmax, double ymin, double ymax, -
//           int axrl=kAxeDirSame, int ayud=kAxeDirSame, bool tmp=false)
//	Définit les limites de coordonnées.
// void	 UpdateLimits()
//	Recalcule les limites de coordonnées à partir du premier Drawer.
// void  SetAxesFlags(unsigned int flags=kAxesDflt)
//	Définit les attributs des axes.
// int  AddScDrawer(PIDrawer*, bool ad=false, bool lock=false)
//	Ajoute un Drawer.
//--


PIScDrawWdg::PIScDrawWdg(PIContainerGen *par, const char *nom,
                         int sx, int sy, int px, int py)
:PIBaseWdg(par, nom, sx, sy, px, py)
{
  mFgReticule = false;
  mCPosX = mCPosY = 0;
  mPPos[0] = mPPos[1] = 0.;
  mPSz[0] = mPSz[1] = 0.;
  mFormatOpt[0] = "%-g"; mFormatOpt[1] = "%-g";
  mFgDeltaPos = false;
  mPosForDelta[0] = mPosForDelta[1] = 0.;
  mPosFDX = mPosFDY = 0;

  mBDrw = new PIElDrawer(false);
  mBDrw->SetName("AxesDrw");
  SetLimits(-1.,1.,-1.,1.,kAxeDirLtoR,kAxeDirDownUp);
  // SetDefaultDrawRectangle(0.12, 0.12, 0.88, 0.88, true); fait par SetAxesFlags() - Reza Mai 2002
  SetAxesFlags(kAxesDflt);
  FreeLimits();
  xEndDrag = yEndDrag = xBegDrag = yBegDrag = 0;
  AddDrawer(mBDrw, true, false, false, true);

//  Pour afficher les coordonnees courante (click-bouton-1)  
  mTrlb = mTxw = NULL;
  mTrW = NULL;
  SetTextWin(NULL);

//  Affichage eventuelle d'infos-texte
  mInfoW = NULL;
  mInfoTxt = NULL;

// Menu pour la manipulation des drawers 
  mDrwMen = NULL;

  ActivateKeyboard();
  ActivateButton(1);    // Pour pouvoir activer la fenetre et coordonnees
  ActivateMove(1);      //    "         "         "        "
  ActivateButton(2);    //  Pour gerer le zoom
  ActivateMove(2);      //    "         "
  ActivateButton(3);    //  Pour definir la zone info-texte
  ActivateMove(3);      //    "         "

}

PIScDrawWdg::~PIScDrawWdg()
{
  delete mBDrw;
  if (mTrW)  delete mTrW;
  if (mInfoW) delete mInfoW;
  if (PIAxesTools::GetCurrentScDrawWdg() == this) 
    PIAxesTools::SetCurrentScDrawWdg(NULL);
  // Pour PIDrwTools, c'est fait par le destructeur de PIBaseWdgGen
  if (mDrwMen) delete mDrwMen;
}

void PIScDrawWdg::Keyboard(int key, PIKeyModifier kmod)
{
if (kmod == PIKM_Alt) {
  if      (key == 'R' || key == 'r')  Refresh(); // rafraichir l'affichage
  else if (key == 'M' || key == 'm') mFgReticule = !mFgReticule; // reticule de mesure 
  else if (key == 'K' || key == 'k') UpdatePosForDeltaMarker(true);
  else if (key == 'L' || key == 'l') UpdatePosForDeltaMarker(false);
  else if (key == 'V' || key == 'v') RequestSelection();  // Pour coller (copier/coller)  
  else if (key == 'Z' || key == 'z') { mBDrw->ElDelAll();  Refresh(); } // Pour supprimer tous les signes 
  else if (key == 'E' || key == 'e') { mBDrw->ElDelLast();  Refresh(); } // Pour supprimer le dernier element ajoute
  else if (key == 'T' || key == 't') { // fenetre des options texte
    PIDrawer* actdrw = GetActiveDrawer();
    if (actdrw != NULL) PIDrwOptionStringWindow::ShowDrwOptionStringWindow(actdrw);
  }
  else if (key == 'O' || key == 'o') { // fenetre des options de controle du drawer actif
    PIDrawer* actdrw = GetActiveDrawer();
    if (actdrw != NULL) actdrw->ShowControlWindow(this);
  }
  else if (key == 'G' || key == 'g') // Fenetre des options graphiques de trace
    PIDrwTools::ShowPIDrwTools(this);   
  
  else if (key == 'A' || key == 'a') { 
    PIAxesTools::SetCurrentScDrawWdg(this);
    PIAxesTools::ShowPIAxesTools();  // Fenetre de gestion des axes
  }
  else if (key == 'D' || key == 'd') {  // Menu de manipulation des drawers
    if (mDrwMen) delete mDrwMen;
    mDrwMen = new PIDrwMgrMenu(this, true);
    mDrwMen->Show();
  }  
  else if (key == 'I' || key == 'i') UpdateInfoWindow();  // Fenetre Text-Info 
  }
}
void 
PIScDrawWdg::PasteSelection(unsigned int typ, void *pdata, unsigned int l)
{
if (typ != PICP_string) return;
int ll = (l<256) ? l+1 : 256;
char pc[256];
strncpy(pc, (char*)pdata, ll-1);  pc[ll-1] = '\0';
mBDrw->ElAddText(mPPos[0], mPPos[1], pc );
mBDrw->Refresh();
}

void
PIScDrawWdg::SetLimits(double xmin, double xmax, double ymin, double ymax,
                       int axrl, int ayud, bool tmp)
{
//  if (xmax <= xmin || ymax <= ymin) {
//    cerr << "PIScDrawWdg::SetLimits() Error - xmax <= xmin or ymax <= ymin !" << endl;
//    return; 
//    }
  double xym;
  xym = fabs(xmax+xmin); xym = (xym > PETIT_DBLE) ? xym : PETIT_DBLE;
  if ((xmax-xmin)/xym < PREC_DBLE) { xmin = xmin - PREC_DBLE/2.*xym;  xmax = xmin + PREC_DBLE*xym; }
  xym = fabs(ymax+ymin); xym = (xym > PETIT_DBLE) ? xym : PETIT_DBLE;
  if ((ymax-ymin)/xym < PREC_DBLE) { ymin = ymin - PREC_DBLE/2.*xym;  ymax = ymin + PREC_DBLE*xym; }

  SetDefaultDrawerLimits(xmin, xmax, ymin, ymax, axrl, ayud);
  mBDrw->SetLimits(xmin, xmax, ymin, ymax, axrl, ayud);
  mPPos[0] = 0.5*(XMin()+XMax());
  mPPos[1] = 0.5*(YMin()+YMax());
  mPSz[0] = 0.05*(XMax()+XMin());
  mPSz[1] = 0.05*(YMax()+YMin());
  if (!tmp) {
    xMinS = xmin;
    xMaxS = xmax;
    yMinS = ymin;
    yMaxS = ymax;
  }
  mFormatOpt[0] = SetFormatOpt(xmin,xmax);
  mFormatOpt[1] = SetFormatOpt(ymin,ymax);
  UpdatePosForDeltaMarker(false, true);
}
  
void
PIScDrawWdg::UpdateLimits()
{
  if (NbDrawers() < 2)  return;
  PIDrawer* d = GetDrawer(1);
  if (d == NULL) return;
  // Le calcul de limites peut dependre du flag AxeLog Yes/No
  // pour le calcul de la marge de garde en particulier. On met 
  // donc les flags AxeLog a jour avant UpdateLimits() Reza+CMV 07/2002
  d->SetLogScale(isDefaultDrawerLogScaleX(), isDefaultDrawerLogScaleY());
  d->UpdateLimits();
  SetLimits(d->XMin(), d->XMax(), d->YMin(), d->YMax(), mDXdir, mDYdir); 
  Refresh();
  return;  
}

void
PIScDrawWdg::SetAxesFlags(unsigned int flags)
{
  mBDrw->SetAxesFlags(flags);
  if ((flags & kBoxAxes) == kBoxAxes) 
    SetDefaultDrawRectangle(0.13, 0.09, 0.93, 0.89, true);
  else 
    SetDefaultDrawRectangle(0.08, 0.08, 0.92, 0.92, true);
}

int 
PIScDrawWdg::DecodeOptionString(vector<string> & opt, bool rmdecopt)
{
  if (opt.size() == 0)  return(0);  
  unsigned int aflg = BaseDrawer()->GetAxesFlags();
  int ndec1 = BaseDrawer()->DecodeOptionString(opt, rmdecopt);
  if (aflg != BaseDrawer()->GetAxesFlags())
    SetAxesFlags(BaseDrawer()->GetAxesFlags());
  vector<string> udopt;
  unsigned int k = 0;
  int ndec = opt.size();
  bool fglinlog = false;
  bool fglogx = isLogScaleX();
  bool fglogy = isLogScaleY();

  // Flag declenchant SetLimits
  bool fgsaxel = false;
  // Limites et sens d'axe
  double xmin = XMin();
  double ymin = YMin();
  double xmax = XMax();
  double ymax = YMax();
  int axrl = kAxeDirLtoR;
  int ayud = kAxeDirDownUp;
  int xac, yac;
  GetAxesConfig(xac, yac);
  if (xac & kAxeDirRtoL) axrl = kAxeDirRtoL;
  if (yac & kAxeDirUpDown) ayud = kAxeDirUpDown;

  for( k=0; k<opt.size(); k++ ) {
    string opts = opt[k];
    // Couleur d'arriere plan du widget
    if (opts.substr(0,7) == "wbgcol=") {
      vector<string> vsc;
      vsc.push_back(opts.substr(7));
      SetBackgroundColor(PIGraphicAtt(vsc).GetColor());
      continue;
    }
    // Limites en x,y
    if (opts.substr(0,9) == "xylimits=") {
      sscanf(opts.substr(9).c_str(),"%lg,%lg,%lg,%lg",&xmin, &xmax,&ymin,&ymax);
      fgsaxel = true;
      continue;
    }
    if (opts.substr(0,10) == "defdrrect=") {
      double x1 = 0.1;
      double y1 = 0.1;
      double x2 = 0.9;
      double y2 = 0.9;
      sscanf(opts.substr(10).c_str(),"%lg,%lg,%lg,%lg",&x1, &x2,&y1,&y2);
      SetDefaultDrawRectangle(x1, y1, x2, y2, true);
      continue;
    }
    if (opts == "linx") {
      fglinlog = true;  fglogx = false;
      continue;
    }
    if (opts == "logx") {
      fglinlog = true;  fglogx = true;
      continue;
    }
    if (opts == "liny") {
      fglinlog = true;  fglogy = false;
      continue;
    }
    if (opts == "logy") {
      fglinlog = true;  fglogy = true;
      continue;
    }
    if ((opts == "revax") || (opts == "axerl") ) {
      fgsaxel = true;  axrl = kAxeDirRtoL;
      continue;
    }
    if ((opts == "revay") || (opts == "axeud") ) {
      fgsaxel = true;  ayud = kAxeDirUpDown;
      continue;
    }
    if (opts == "axelr") {
      fgsaxel = true;  axrl = kAxeDirLtoR;
      continue;
    }
    if (opts == "axedu") {
      fgsaxel = true;  ayud = kAxeDirDownUp;
      continue;
    }

// Les autres attributs d'axes (stdaxes boxaxesgrid ...) sont decodes par PIElDrawer

    ndec--;
    if (rmdecopt)  udopt.push_back(opts);
  }  

  if (fgsaxel)  SetLimits(xmin, xmax, ymin, ymax, axrl, ayud);
  if (fglinlog) SetLogScale(fglogx, fglogy);

  if (rmdecopt)  opt = udopt;
  return(ndec+ndec1);
}

int 
PIScDrawWdg::AddScDrawer(PIDrawer* d, bool ad, bool lock)
{
  if (d == NULL)  return(-1);
  if (! LimitsFixed() ) {  //  On met a jour les limites 
    // Le calcul de limites peut dependre du flag AxeLog Yes/No
    // pour le calcul de la marge de garde en particulier. On met 
    // donc les flags AxeLog a jour avant UpdateLimits() Reza+CMV 07/2002
    d->SetLogScale(isDefaultDrawerLogScaleX(), isDefaultDrawerLogScaleY());
    d->UpdateLimits();
    SetLimits(d->XMin(), d->XMax(), d->YMin(), d->YMax(), mDXdir, mDYdir);
  }
  return(AddDrawer(d, true, true, ad, lock));
}


void
PIScDrawWdg::SetTextWin(PILabel * tw, bool trw, int tx, int ty)
{
mTxw = tw;
if (trw)
  {
  if (mTrW)  mTrW->SetSize(tx, ty);
  else
    {
    mTrW = new PIWindow(this, "Point", PIWK_transient, tx, ty, 0, 0);
    mTrW->SetAutoDelChilds(true);
    mTrlb = new PILabel(mTrW, "PointCoord", tx, ty, 0, 0);
    mTrlb->SetBinding(PIBK_fixed,PIBK_fixed, PIBK_fixed,PIBK_fixed);
    }
  }
else
  if (mTrW) { delete mTrW; mTrW = NULL;  mTrlb = NULL; }

return;
}



// Gestion affichage coordonnees du point 

void
PIScDrawWdg::GetClickText(string& info, double x, double y) 
// Donne le texte a afficher pour position x,y  
{
  char buff[64];
  PIDrawer*  dr = GetActiveDrawer();

  info+="X=";  sprintf(buff,mFormatOpt[0].c_str(),x); info += buff;
  info+=" Y="; sprintf(buff,mFormatOpt[1].c_str(),y); info += buff;
  if(mFgDeltaPos) {
    sprintf(buff," (dX=%g, dY=%g)",x-mPosForDelta[0],y-mPosForDelta[1]); 
    info += buff;
  }

  if (dr) {
    info += " ";  // info += dr->Name();
    dr->GetClickInfo(info,x,y,mPosForDelta[0],mPosForDelta[1],mFgDeltaPos);
  }
  return;
}

void
PIScDrawWdg::ActivateSpecializedControls()
// Par défaut affiche la fenetres des attributs graphiques et axes
{
  PIDrwTools::SetCurrentBaseWdg(this);
  PIDrwTools::ShowPIDrwTools();   // Fentre axes et options de trace
}

void
PIScDrawWdg::UpdateInfoWindow()
{

if (mInfoW == NULL) { // Creation de la fenetre info
  string nom = Nom() + "-Info";
  int tpx, tpy;
  GetScreenPos(tpx, tpy);
  int sx, sy;
  int ssx, ssy;
  PIApplicationScreenSize(ssx, ssy);
  if ( (ssx > 1000) && (ssy > 1000) ) { sx = 400;  sy = 200; }
  else { sx = 300; sy = 160; }
  mInfoW = new PIWindow(this, nom.c_str(), PIWK_normal,  sx, sy, tpx, tpy+YSize()+10);
  mInfoW->SetAutoDelChilds(true);
  nom = Nom() + "-InfoText";
  mInfoTxt = new PIText(mInfoW, nom.c_str(), true, true, sx, sy, 0, 0);
  mInfoTxt->SetBinding(PIBK_fixed, PIBK_fixed, PIBK_fixed, PIBK_fixed);
  mInfoTxt->SetMutiLineMode(true);
  mInfoTxt->SetTextEditable(false);
  }

//  Boucle sur tous les drawers :
vector<BWDrwId>::iterator it;
char buff[128];
sprintf(buff, "Info: NDrawer= %d - Pos=%g %g  (Sz=%g,%g) \n", (int)mDrwList.size()-1, 
        mPPos[0], mPPos[1], mPSz[0], mPSz[1] );
double xmin, ymin, xmax, ymax;
xmin = mPPos[0] - 0.5*mPSz[0];
xmax = mPPos[0] + 0.5*mPSz[0];
ymin = mPPos[1] - 0.5*mPSz[1];
ymax = mPPos[1] + 0.5*mPSz[1];

string info = buff;
int k=0;
for(it = mDrwList.begin(); it != mDrwList.end(); it++) {
  if ((*it).drw == mBDrw )  continue;
  k++;
  sprintf(buff," --------- Drawer %d ----------- \n", k); 
  info += buff; 
  (*it).drw->AppendTextInfo(info, xmin, ymin, xmax, ymax);
  }

mInfoW->Show();
mInfoTxt->Manage();
mInfoTxt->SetText(info);
}

// .............................
// Bouton-1 : Position courante 

void
PIScDrawWdg::But1Press(int x, int y)
{
  PIKeyModifier kmod;
  unsigned long tm;
  GetLastEventInfo(kmod, tm);
  // cmv+rz 21/08/2007 : pour eviter le plantage suite pb d'evenement eXpose non delivre par 
  // le serveur X (x.org) sous Linux - 
  if (mBDrw->GetGraphicUC() == NULL)  Refresh();
  // ----- Fin modif du 21/08/2007   
  UpdateText(x, y);
  if (mTrW)
    { 
    int tpx, tpy;
    GetScreenPos(tpx, tpy);       
    tpy -= (mTrW->YSize()+5);
    if (tpy < 0)  tpy = 0;
    mTrW->SetPos(tpx, tpy);
    mTrW->Show();
    }
  if (mFgReticule || mFgDeltaPos) { // On trace une reticule
    cForCol = mWGrC->GetForeground();
    cGOmod  = mWGrC->GetGOMode();
    cLatt = mWGrC->GetLineAtt();
    mWGrC->SelForeground(PI_Magenta);
    mWGrC->SelGOMode(PI_GOXOR);
    mWGrC->SelLine(PI_ThinLine);
  }
  if (mFgReticule)  DrawReticule(x,y,0);
  else SelPointerShape(PI_CrossPointer);
  if (mFgDeltaPos)  DrawDeltaPosMarker();

  Send(Msg(), PIMsg_Active);
  PIDrwTools::SetCurrentBaseWdg(this);
  PIAxesTools::SetCurrentScDrawWdg(this);
}

void
PIScDrawWdg::Ptr1Move(int x, int y)
{
  UpdateText(x, y);  // Met a jour mPPos
  if (mFgReticule)  DrawReticule(x,y,1);
}

void
PIScDrawWdg::But1Release(int x, int y)
{  
  UpdateText(x, y);
  if (mFgReticule)  DrawReticule(x,y,2);
  else SelPointerShape(PI_ArrowPointer);
  if (mFgDeltaPos)  DrawDeltaPosMarker();
  if (mFgReticule || mFgDeltaPos) {
    mWGrC->SelForeground(cForCol);
    mWGrC->SelGOMode(cGOmod);
    mWGrC->SelLine(cLatt);
  }
  if (mTrW)  mTrW->Hide();
}

void
PIScDrawWdg::UpdateText(int xp, int yp)
{
  double dx, dy;
  mBDrw->GetGraphicUC()->GrC2UC(xp, yp, dx, dy); 
  mPPos[0] = dx;  mPPos[1] = dy; 
  
  string ctxt;
  GetClickText(ctxt, dx, dy);
//DEBUG  char buff[32];    sprintf(buff, " %d:%d",xp,yp); ctxt += buff;
  if (mTxw)
    mTxw->SetLabel(ctxt);
  if (mTrlb)
    mTrlb->SetLabel(ctxt);
  return;

}

void
PIScDrawWdg::UpdatePosForDeltaMarker(bool fg, bool fgupd)
{
  if (!fgupd)   mFgDeltaPos = fg;
  if (mFgDeltaPos) {
    mPosForDelta[0] = mPPos[0];  
    mPosForDelta[1] = mPPos[1];  
    double pfdx, pfdy;
    mBDrw->GetGraphicUC()->UC2GrC(mPosForDelta[0], mPosForDelta[1], 
				 pfdx, pfdy); 
    mPosFDX = (int)pfdx;  mPosFDY = (int)pfdy;
  }
  return;
}


void
PIScDrawWdg::DrawReticule(int x, int y, int op)
{
  if (!mFgReticule) return;
  //  int pos = (x>XSize()/2) ? PI_HorizontalRight: PI_HorizontalLeft;
  //  char buff[128];
  //  string format1 = "X= "; format1 += mFormatOpt[0].c_str();
  //  string format2 = "Y= "; format2 += mFormatOpt[1].c_str();
  if (op > 0) { // on efface le precedent 
    mWGrC->DrawLine(mCPosX, 0, mCPosX, YSize());
    mWGrC->DrawLine(0, mCPosY, XSize(), mCPosY);
    //    sprintf(buff,format1.c_str(), mPPos[0]);
    //    mWGrC->DrawString(mCPosX+10, mCPosY-10, buff, pos); 
    //    sprintf(buff,format2.c_str(), mPPos[1]);
    //    mWGrC->DrawString(mCPosX+10, mCPosY+20, buff, pos); 
  }
  if (op < 2) {
    mWGrC->DrawLine(x, 0, x, YSize());
    mWGrC->DrawLine(0, y, XSize(), y);
    mCPosX = x;   mCPosY = y;
  }  
}

void
PIScDrawWdg::DrawDeltaPosMarker()
{
  if (mFgDeltaPos) {
    mWGrC->DrawLine(mPosFDX-14., mPosFDY, mPosFDX+14, mPosFDY);
    mWGrC->DrawLine(mPosFDX, mPosFDY-14, mPosFDX, mPosFDY+14);
  }  
}

// .............................
// Bouton-2 Gestion du zoom 

void
PIScDrawWdg::But2Press(int x, int y)
{
  // cmv+rz 21/08/2007 : On rafraichit la fenetre si d'evenement eXpose non delivre  
  if (mBDrw->GetGraphicUC() == NULL)  Refresh();
  // ----- Fin modif du 21/08/2007   
  xEndDrag = xBegDrag = x;
  yEndDrag = yBegDrag = y;
  cForCol = mWGrC->GetForeground();
  cGOmod  = mWGrC->GetGOMode();
  cPointer = GetPointerShape();
  cLatt = mWGrC->GetLineAtt();
  SelPointerShape(PI_CrossPointer);
  mWGrC->SelForeground(PI_Magenta);
  mWGrC->SelGOMode(PI_GOXOR);
  mWGrC->SelLine(PI_ThinLine);
  Send(Msg(), PIMsg_Active);
  PIDrwTools::SetCurrentBaseWdg(this);
  PIAxesTools::SetCurrentScDrawWdg(this);
}

void
PIScDrawWdg::But2Release(int /*x*/, int /*y*/)
{

  mWGrC->DrawBox(xBegDrag, yBegDrag, xEndDrag-xBegDrag, yEndDrag-yBegDrag);

  mWGrC->SelForeground(cForCol);
  mWGrC->SelGOMode(cGOmod);
  SelPointerShape(cPointer); 
  mWGrC->SelLine(cLatt); 

  //  Pour rendre le changement de zoom moins delicat $REZA - 05/99$  
  int dxd = xEndDrag-xBegDrag;
  if (dxd < 0) dxd = -dxd;
  int dyd = yEndDrag-yBegDrag;
  if (dyd < 0) dyd = -dyd;
  //  if (xBegDrag == xEndDrag || yBegDrag == yEndDrag) // $REZA - 05/99$  
  if ( (dxd < 5) || (dyd < 5) )    // $REZA - 05/99$  
    SetLimits(xMinS, xMaxS, yMinS, yMaxS, kAxeDirSame, kAxeDirSame );
  else {
    double xl,yl,xh,yh;
    mBDrw->GetGraphicUC()->GrC2UC(xBegDrag, yBegDrag, xl, yl);
    mBDrw->GetGraphicUC()->GrC2UC(xEndDrag, yEndDrag, xh, yh);
    if (xl > xh) dbl_swap(xl, xh);
    if (yl > yh) dbl_swap(yl, yh);
    SetLimits(xl,xh,yl,yh, kAxeDirSame, kAxeDirSame, true);
  }
  
  Refresh();
}

void
PIScDrawWdg::Ptr2Move(int x, int y)
{
  mWGrC->DrawBox(xBegDrag, yBegDrag, xEndDrag-xBegDrag, yEndDrag-yBegDrag);
  xEndDrag = x;
  yEndDrag = y;
  mWGrC->DrawBox(xBegDrag, yBegDrag, xEndDrag-xBegDrag, yEndDrag-yBegDrag);
}


// .............................
// Bouton-3 : Gestion de definition de la taille de rectangle Text-Info

void
PIScDrawWdg::But3Press(int x, int y)
{
  // cmv+rz 21/08/2007 : On rafraichit la fenetre si d'evenement eXpose non delivre  
  if (mBDrw->GetGraphicUC() == NULL)  Refresh();
  // ----- Fin modif du 21/08/2007   
  xEndDrag = xBegDrag = x;
  yEndDrag = yBegDrag = y;
  cForCol = mWGrC->GetForeground();
  cGOmod  = mWGrC->GetGOMode();
  cPointer = GetPointerShape();
  cLatt = mWGrC->GetLineAtt();
  SelPointerShape(PI_CrossPointer);
  mWGrC->SelForeground(PI_Magenta);
  mWGrC->SelGOMode(PI_GOXOR);
  mWGrC->SelLine(PI_ThinLine);
  Send(Msg(), PIMsg_Active);
  PIDrwTools::SetCurrentBaseWdg(this);
  PIAxesTools::SetCurrentScDrawWdg(this);
}

void
PIScDrawWdg::But3Release(int /*x*/, int /*y*/)
{

  mWGrC->DrawBox(xBegDrag, yBegDrag, xEndDrag-xBegDrag, yEndDrag-yBegDrag);

  mWGrC->SelForeground(cForCol);
  mWGrC->SelGOMode(cGOmod);
  SelPointerShape(cPointer); 
  mWGrC->SelLine(cLatt); 

  double xl,yl,xh,yh;
  mBDrw->GetGraphicUC()->GrC2UC(xBegDrag, yBegDrag, xl, yl);
  mBDrw->GetGraphicUC()->GrC2UC(xEndDrag, yEndDrag, xh, yh);
  if (xl > xh) dbl_swap(xl, xh);
  if (yl > yh) dbl_swap(yl, yh);
  mPPos[0] = 0.5*(xl+xh);
  mPPos[1] = 0.5*(yl+yh);
  mPSz[0] = xh-xl;
  mPSz[1] = yh-yl;
  mCPosX =  0.5*(xBegDrag+xEndDrag);
  mCPosY =  0.5*(yBegDrag+yEndDrag);

  return;
}

void
PIScDrawWdg::Ptr3Move(int x, int y)
{
  mWGrC->DrawBox(xBegDrag, yBegDrag, xEndDrag-xBegDrag, yEndDrag-yBegDrag);
  xEndDrag = x;
  yEndDrag = y;
  mWGrC->DrawBox(xBegDrag, yBegDrag, xEndDrag-xBegDrag, yEndDrag-yBegDrag);
}

string
PIScDrawWdg::SetFormatOpt(double xmin,double xmax)
{
  string format = "%-g";
  double xm = (fabs(xmax)>fabs(xmin)) ? fabs(xmax): fabs(xmin);
  double dx = fabs(xmax-xmin)/500.;
  PIAxes::BonFormatAxes(xm,xm+dx,dx,format,0,1);
  return format;
}
