#include <stdio.h>
#include "piapplgen.h"
#include "pihisto2d.h"
#include "nbrandom.h"

static int dbg = 0;

//++
// Class	PIHisto2D,PIH2DWdg,H2WinArg
// Lib	PI
// include	pihisto2d.h
//
//	Classes de dessin des histogrammes a 2 dimensions.
//--

//++
// Titre	Dessin d'un histogramme 2D.
//--

//++
PIHisto2D::PIHisto2D(Histo2D* histo, bool ad)
//
//	Createur d'une classe de dessin pour l'histogramme 2D histo.
//--
: PIDrawer(), mHisto(histo)
{
mAdDO = ad;     // Flag pour suppression automatique de mHisto  

mLogScale = 10.;
mFPoints = 0.5;

UseColors();
UseDisplay();
UseDyn();
UseFrac();
}

//++
PIHisto2D::~PIHisto2D()
//
//	Destructeur.
//--
{
if(mAdDO) delete mHisto;
}

//++
void PIHisto2D::UseColors(bool fg, CMapId cmap)
//
//	Choix de la couleur si fg=true avec la color map cmap.
//	(pour la couleur cmap cf picmap.h).
//      Independamment du choix du display, la dynamique est
//      codee sur la color map donnant ainsi une double
//      information. Par exemple, carres de tailles variables
//      en couleur. Cette option est incontournable dans le cas
//      d'un display par des carres de taille fixe.
//--
{
mFgCol = fg; mCmap = cmap;
}

//++
void PIHisto2D::UseScale(unsigned short type,float logscale)
//
//	Pour changer les echelles (lineaire ou logarithmique)
//| Type = 0 : echelle lineaire
//|      = 1 : echelle log10
//| -**- Explication du codage en type=0 (lineaire) :
//|   1. [hmin,hmax] -> [0,1]
//|           h      ->   f = (h-hmin)/(hmax-hmin)
//|   2. codage de f=[0,1] sur la dynamique du display choisi
//| -**- Explication du codage en type=1 (logarithmique base 10) :
//|   1. map lineaire entre 0 et 1:
//|      [hmin,hmax] -> [0,1]
//|           h      ->   f = (h-hmin)/(hmax-hmin)
//|   2. transformation logarithmique de base 10 :
//|      [0,1] -> [0,1]
//|        f   -> lf = log10(1.+f*(logscale-1))/log10(logscale)
//|   3. codage de lf=[0,1] sur la dynamique du display choisi
//--
{
if(type==0) mTypScal = 0;
if(type==1) {
  mTypScal = 1;
  if(logscale>1.) mLogScale = logscale;
} else mTypScal = 0;
}

//++
void PIHisto2D::UseDisplay(unsigned short type, float fnpt)
//
//	Type de Display
//| Type = 0 : carres de tailles variables
//| Type = 1 : nuages de points
//|            Le nombre de points a utiliser est fnpt*N
//|            ou N est le nombre de pixels ecran contenu
//|            dans un bin de l'histogramme.
//| Type = 2 : code a la "hbook2" " .+123...9AB...YZ*"
//|            (cf detail PIHisto2D::HPrint2)
//| Type = 3 : carres de taille fixe (couleur).
//--
{
if(fnpt<0.) fnpt=0; else if(fnpt>1.) fnpt=1.;
if(type==0)        mTypDisp = 0;
else if(type==1) { mTypDisp = 1; mFPoints = fnpt;}
else if(type==2)   mTypDisp = 2;
else if(type==3)   mTypDisp = 3;
else               mTypDisp = 1;
}

//++
void PIHisto2D::UseDyn(float hmin, float hmax)
//
//	Gestion de la dynamique a representer:
//|  La dynamique va etre transformee de [hmin,hmax] vers [0,1] selon
//|  [hmin,hmax] -> [0,1]
//|       h      ->   f = (h-hmin)/(hmax-hmin)
//|  Par la suite selon ce qui est demande, f va coder le display ou etre
//|  transforme en une autre echelle [0,1].
//|  Si hmax<=hmin, ils sont forces a la dynamique totale de l'histo2D.
//--
{
if(hmin>=hmax) {hmin = mHisto->VMin(); hmax = mHisto->VMax();}
if(hmin>=hmax) hmax = hmin+1.;
mHMin = hmin; mHMax = hmax;
}

//++
void PIHisto2D::UseFrac(float frmin, float frmax)
//
//	Pour definir la fraction de la dynamique a dessiner:
//| Certains type de display (f=[0,1] cf PIHisto2D::UseDyn),
//|  - on ne dessine rien si f <= frmin dans les cas de display avec
//|    des nuages de points ou des carres de tailles variables.
//|    Pour un display "a la hbook2" on force frmin = 0.
//|  - frmax n'est utilise que pour la representation avec
//|    des carres de tailles variables: c'est la taille
//|    maximum que peut avoir le carre exprimee en unite
//|    de la taille du bin (ex: si frmax=0.8 le carre
//|    le + grand qui pourra etre dessine dans un bin
//|    aura une taille egale a 0.8*(taille du bin)).
//--
{
if(frmax<=0. || frmax>1.) frmax = 1.;
if(frmin>=frmax) {frmin=0.1; frmax=0.9;}
mFracMin = frmin; mFracMax = frmax;
}

//++
void PIHisto2D::Print(int lp)
//
//	Print de l'etat des options du display.
//--
{
printf("PIHisto2D::Print FgCol=%d Cmap=%d TypScal=%d TypDisp=%d (FPoints=%g)\n"
      ,(int)mFgCol,(int)mCmap,mTypScal,mTypDisp,mFPoints);
printf("                 Dyn=%g,%g Frac=%g,%g LogSc=%g H=%lx\n"
      ,mHMin,mHMax,mFracMin,mFracMax,mLogScale,(long)mHisto);
if(lp<1) return;
mHisto->PrintStatus();
}

//++
void PIHisto2D::UpdateLimits()
//
//	Definition des tailles graphiques en fonction
//	des caracteristiques de l'histogramme a dessiner.
//--
{
  if(!mHisto) return;
  SetLimits(mHisto->XMin(), mHisto->XMax(), mHisto->YMin() , mHisto->YMax());
  SetAxesFlags(kBoxAxes | kExtTicks | kLabels);
}

//++
void PIHisto2D::Draw(PIGraphicUC* g, double xmin, double ymin, double xmax, double ymax)
//
//	Dessin de l'histogramme.
//|  Code de dessin selon choix des options:
//|  (detail voir UseColors UseScale UseDisplay UseDyn UseFrac)
//|  [hmin,hmax] -> [0,1] [[ -> re-codage log10 entre [0,1] ]] -> f=[0,1]
//|  Puis selon display:
//|  0 carres variables : if(f>fracmin) taille carre = f*fracmax *taille_du_bin
//|  1 nuage de points  : if(f>fracmin) npoints = f*PerPt *npoints_ecran_dans_bin
//|  2 code hbook2      : if(f>0) map de f=]0,1] dans ".+...Z*"
//|  3 carres fixes     : couleur = lut[f*nombre_d_entree_dans_la_lut]
//--
{
if(!mHisto) return;
// Caracteristiques histogramme
double dx = mHisto->WBinX(),dy = mHisto->WBinY();
double p1dx,p1dy;
g->DGrC2UC(1.f,1.f,p1dx,p1dy);

// Gamme a representer entre [0,1] mais >=fracmin et scale fracmax
float fracmin=FMin(), fracmax=FMax();
float llscale = (float) log10((double)LogScale());

// gestion Couleurs.
PIColorMap* cmap=NULL;
PIColors coul = g->GetForeground();
int ncol = 0;
if (mFgCol) {
  cmap = new PIColorMap(mCmap); ncol = cmap->NCol();
  if(mTypDisp==3) fracmin=-1.;
}

// gestion epaisseur de ligne
if (mLAtt == PI_NotDefLineAtt)  g->SelLine(PI_ThinLine);

// gestion Markers ou plot avec des points.
PIMarker Mk = g->GetMarker();
int MkSz = g->GetMarkerSize();
int npt = 1;
if(mTypDisp==1) {
  g->SelMarker(1,PI_DotMarker);
  npt = (int) ((float)NPixBin(g)*FPoints()); if(npt<=0) npt = 2;
}

// gestion Font.
PIFontAtt FontAtt = g->GetFontAtt();
int FontSize = g->GetFontSize();
if(mTypDisp==2) {
  double dxg,dyg,dg;
  g->DUC2GrC(dx,dy,dxg,dyg);
  dg =(dxg<dyg) ? dxg : dyg;
  int npix = (int) (dg*0.9); if(npix<8) npix = 8;
  //printf("PIHisto2D::Draw_Font H dx=%g dy=%g, G dx=%g dy=%g, npix = %g,%d\n"
  //      ,dx,dy,dxg,dyg,dg,npix);
  g->SelFontSzPt(npix,PI_RomanFont);
  fracmin = 0;
}

// Print();

// Plot de l'histogramme
for (int i=0; i<mHisto->NBinX(); i++)
for (int j=0; j<mHisto->NBinY(); j++) {

  float left0,bottom0;
  mHisto->BinLowEdge(i,j,left0,bottom0);

  // Gestion de la dynamique a dessiner
  float frac = ((*mHisto)(i,j)-HMin())/(HMax()-HMin());
  if(frac<0.) continue;
  if(mTypScal==1) {              // echelle log10
    frac = log10(1.+frac*(LogScale()-1.))/llscale;
    if(frac<0.) continue;
  }
  if(frac<=fracmin) continue;
  if(frac>1.) frac = 1.;
  float fracred = frac * fracmax;

  // Gestion de la couleur
  int icol = 0;
  if (cmap) {
    icol = int( (float) ncol*frac );
    if(icol>=ncol) icol = ncol-1; else if(icol<0) icol=0;
    g->SelForeground(*cmap,icol);
  }

// Pour ne pas dessiner en dehors des axes 
  if ( (left0+dx/2. < xmin) || (left0+dx/2. > xmax) || 
         (bottom0+dy/2. < ymin) || (bottom0+dy/2. > ymax) ) continue;

  // Dessin proprement dit selon le choix graphique.
  if(mTypDisp==0) {
    //..... carres de tailles variables
    double left   = left0   + 0.5*(1.-fracred)*dx, width  = fracred*dx;
    double bottom = bottom0 + 0.5*(1.-fracred)*dy, height = fracred*dy;
    if (cmap) g->DrawFBox(left,bottom,width,height);
    else      g->DrawBox(left,bottom,width,height);
  } else if(mTypDisp==1) {
    //..... nuage de points .....
    int ipt  = int( (float) npt *frac );
    for(int k=0;k<ipt;k++) {
      double x = left0 + frand01()*dx;
      double y = bottom0 + frand01()*dy;
      g->DrawMarker(x,y);
    }
  } else if(mTypDisp==2) {
    //..... type hbook2/hprint .+23-Z*
    char c[2];
    c[0] = HPrint2(frac); c[1]='\0';
    double x = left0 + dx/2.;
    double y = bottom0 + dy/2.;
    g->DrawString(x,y,c);
  } else if(mTypDisp==3) {
    //..... carres de tailles fixes (avec gestion de continuite)
    if (cmap) g->DrawFBox(left0,bottom0,dx+p1dx,dy+p1dy);
    else      g->DrawBox(left0,bottom0,dx+p1dx,dy+p1dy);
  }

}

// Remise dans les conditions ulterieures pour la suite du graphique.
g->SelMarker(MkSz,Mk);
g->SelForeground(coul);
g->SelFontSzPt(FontSize,FontAtt);
if (cmap) delete cmap;

// Fin du dessin, ecriture de la statistique.
DrawStats(g);
}

//++
void PIHisto2D::DrawStats(PIGraphicUC* g)
//
//	Dessin des informations statistiques de l'histogramme.
//--
{
  // Une boite dans le coin superieur droit
  if (mLAtt == PI_NotDefLineAtt)  g->SelLine(PI_ThinLine);
  double cellHeight = (YMax() - YMin()) * 0.05;
  double cellWidth  = (XMax() - XMin()) * 0.23;
  g->DrawLine(XMax() - cellWidth, YMax(),
                       XMax() - cellWidth, YMax() - cellHeight);
  g->DrawLine(XMax() - cellWidth, YMax() - cellHeight,
                       XMax()            , YMax() - cellHeight);
  char label[50];
  sprintf(label, "N = %.6g", mHisto->NData());
  g->SelFontSz((YMax() - YMin())/30);
  g->DrawString(XMax() - cellWidth*0.9, YMax() - cellHeight*0.8, label);
  printf("H[%d,%d] Dynamique: [%g,%g] Frac [%g,%g]\n"
        ,mHisto->NBinX(),mHisto->NBinY(),HMin(),HMax(),FMin(),FMax());
}

//++
char PIHisto2D::HPrint2(float f)
//
//	Codage des valeurs en caracteres (fct privee).
//| f entre [0,1] mappee entre valeur=[0,37]
//| si <0 alors =0, si >1 alors 1
//| Display 4   ==> 4<=valeur<5
//|         C   ==> 12<=valeur<13
//|             ==> valeur<=0
//|         *   ==> valeur>=1
//|         .   ==> 0<valeur<1
//|------------------------------------------
//|            C1111111111222222222233333333
//|  C01234567890123456789012345678901234567
//| " .+23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*"
//|------------------------------------------
//--
{
char str[39] = " .+23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ*";
int i;
if(f<=0.) i = 0;
else if(f>=1.) i = 37;
else { i = (int) (f*36.); i++;}
if(i<0) i=0; else if (i>=38) i = 37;
return str[i];
}

//++
int PIHisto2D::NPixBin(PIGraphicUC* g)
//
//	Nombre de pixels ecran dans un bin d'histogramme
//	(fct privee).
//--
{
double dx = mHisto->WBinX(),dy = mHisto->WBinY();
double dxg,dyg;
g->DUC2GrC(dx,dy,dxg,dyg);
int np = (int) dxg * (int) dyg;
//printf("PIHisto2D::NPixBin H dx=%g dy=%g, G dx=%g dy=%g, np = %d\n"
//      ,dx,dy,dxg,dyg,np);
return np;
}


/////////////////////////////////////////////////////////////////
//  Classe PIH2DWdg
/////////////////////////////////////////////////////////////////
//++
// Titre	Widget de dessin d'un histogramme 2D.
//--

static H2WinArg* h2dWinArg=NULL;
static int nb_h2dWinArg = 0;

//++
PIH2DWdg::PIH2DWdg(PIContainerGen *par, char *nom, int sx, int sy, int px, int py)
//
//	Createur d'un Widget de dessin d'histogramme 2D.
//	Le menu pour choisir les options d'affichage apparait
//	suite au clic du bouton-3 de la souris (cf H2WinArg::H2WinArg).
//--
: PIScDrawWdg(par,nom,sx,sy,px,py)
{
if (!h2dWinArg) h2dWinArg = new H2WinArg(this);
nb_h2dWinArg++;
if(dbg) printf("PIH2DWdg::PIH2DWdg %lx h2dWinArg=%lx %d\n"
              ,(long)this,(long)h2dWinArg,nb_h2dWinArg);
mPih = NULL;
// Pour afficher le menu option de trace
ActivateButton(3);
}

//++
PIH2DWdg::~PIH2DWdg()
//
//	Destructeur.
//--
{
nb_h2dWinArg--;
if (nb_h2dWinArg == 0) {
  h2dWinArg->Hide();
  delete h2dWinArg;
  h2dWinArg=NULL;
}
if(dbg) printf("PIH2DWdg::~PIH2DWdg h2dWinArg=%lx %d\n"
              ,(long)h2dWinArg,nb_h2dWinArg);
if (mPih) delete mPih;
}

//++
void PIH2DWdg::SetHisto(Histo2D* histo)
//
//	Pour connecter un histogramme 2D au Widget.
//--
{
if (!histo) return;
if (mPih)  delete mPih;
mPih = new PIHisto2D(histo, true);
AddScDrawer(mPih);
if(dbg) printf("PIH2DWdg::SetHisto mPih=%lx\n",(long)mPih);
}

//++
void PIH2DWdg::SetPIHisto(PIHisto2D* pih2)
//
//	Pour connecter un traceur (Drawer) d'histo 2D au Widget.
//--
{
if (!pih2) return;
if (mPih)  delete mPih;
mPih = pih2;
AddScDrawer(mPih);
if(dbg) printf("PIH2DWdg::SetPIHisto mPih=%lx\n",(long)mPih);
}

//++
string  PIH2DWdg::GetClickText(double x, double y)
//
//	Quand on click (and drag) le bouton-1, affichage
//	des positions x,y et de la valeur du bin de l'histogramme 2D.
//--
{
int i,j;
char str[128];

if ((!mPih) || (!mPih->Histogram())) {
  sprintf(str,"X=%g Y=%g ???",x,y);
  return((string)str);
}

Histo2D* h = mPih->Histogram();

h->FindBin(x,y,i,j);
if(i<0 || i>=h->NBinX() || j<0 || j>=h->NBinY())
  sprintf(str,"x= %g y= %g ???",x,y);
else sprintf(str,"x= %g y= %g v= %g",x,y,(*h)(i,j));

return((string)str);
}

//++
void PIH2DWdg::ActivateSpecializedControls()
//	Pour activer les contrôles spécifiques pour l'affichage Histo-2D	
//--
{
h2dWinArg->SetPIH2DWdg(this);
h2dWinArg->SetMsgParent((PIMsgHandler*)this);
if(!h2dWinArg->Visible()) h2dWinArg->Show();
}

//++
void PIH2DWdg::But3Press(int x, int y)
//
//	Gestion de l'utilisation du bouton-3 de la souris.
//	Un seul objet est cree pour tous les histogrammes 2D.
//	Il est connecte a un histogramme donnee par l'action du
//	du bouton-3 de la souris dans la fenetre contenant
//	le dessin de l'histogramme (cf H2WinArg::H2WinArg).
//--
{
ActivateSpecializedControls();
if(dbg) printf("PIH2DWdg::But3Press(%d,%d) h2dWinArg=%lx\n"
              ,x,y,(long)h2dWinArg);
}


/////////////////////////////////////////////////////////////////
//  Classe H2WinArg
/////////////////////////////////////////////////////////////////
//++
// Titre	Fenetre de dialogue pour le choix des options..
//--

//++
H2WinArg::H2WinArg(PIH2DWdg *par)
//
//	Creation de la fenetre de gestion des parametres
//	des dessins des histogrammes 2D. Cette fenetre de
//	dialogue est partagee par tous les widget de dessin
//	des histogrammes 2D. Pour la faire apparaitre pour la
//	faire apparaitre la premiere fois, cliquez avec le bouton
//	numero 3 de la souris (bouton de droite) dans la fenetre
//	de dessin de l'histogramme. Si elle est deja presente,
//	pour la connecter a une autre fenetre de dessin cliquez avec
//	le meme bouton dans cette fenetre.
//--
//++
//| - Menu 1: Choix du type de display
//|     Carres variables, nuages de points, caracteres a la hbook2
//|     et carres de tailles fixe (couleur ou niveauz de gris).
//| - Menu 2: Choix du type d'echelle
//|     Lineaire ou logarithmique
//| - Menu 3: Choix de la couleur
//|     noir et blanc, niveau de gris et couleurs diverses.
//| - Champ texte Dyn: Pour donner la dynamique, si min>=max
//|     alors prend le min et le max de l'histogramme
//| - Champ texte Frac: fraction mini et maxi
//|     (cf PIHisto2D::UseFrac)
//| - Champ texte LogScal: niveau de scaling pour le choix d'une
//|     echelle logarithmique (cf PIHisto2D::UseScale)
//--
//++
//| - Curseur interactif PerPt: pourcentage de points a dessiner
//|     dans chaque bin (cf PIHisto2D::UseDisplay)
//| - Bouton Apply: dessiner avec les options affichees
//| - Bouton Dismiss: fermeture de la fenetre de dialogue.
//| - Bouton Get: re-prendre les valeurs de display stoquees
//|     pour un histogramme donne.
//| - Bouton Print: Imprimer les caracteristiques du display
//|     et de l'histogramme.
//--
: PIWindow((PIMsgHandler *)par, "Options", PIWK_dialog,250,260,150,150)
{
string sdum;
if(dbg) printf("H2WinArg::H2WinArg %lx par=%lx\n",(long)this,(long)par);

mH2Wdg = NULL;

// Valeurs par defaut
mFgCol    = false;
mCmap     = CMAP_GREYINV32;
mTypScal  = 0;
mTypDisp  = 0;
mFPoints  = 0.5;
mHMin     = 1.;
mHMax     = -1.;
mFracMin  = 0.1;
mFracMax  = 0.9;
mLogScale = 10.;

// Taille automatique
int bsx, bsy;
PIApplicationPrefCompSize(bsx, bsy);  // environ 6 lettres
int spx = (bsx>=10) ? bsx/10 : 1;  // intervalle entre lettres X
int spy = (bsy>=5) ? bsy/5 : 1;    // intervalle entre lettres Y
int wszx = 5*spx+bsx+int(2.5*bsx); // Taille fenetre en X
int wszy = 11*spy+8.5*bsy;           // Taille fenetre en Y
SetSize(wszx, wszy);

// menus bar
  int cpx = 2*spx, cpy = 2*spy;
mOPop[0] = new PIOptMenu(this, "optmen-h2d-1" ,2*bsx,bsy,cpx,cpy);
mOPop[0]->AppendItem("Carres Var."  , 6101);
mOPop[0]->AppendItem("....."        , 6102);
mOPop[0]->AppendItem(".+12..Z*"     , 6103);
mOPop[0]->AppendItem("Carres Pleins", 6104);
sdum = "Carres Var."; mOPop[0]->SetValueStr(sdum);
mOPop[0]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);

  cpy += bsy+spy;
mOPop[1] = new PIOptMenu(this, "optmen-h2d-2",2*bsx,bsy,cpx,cpy);
mOPop[1]->AppendItem("Lineaire", 6201);
mOPop[1]->AppendItem("Log10"   , 6202);
sdum = "Lineaire"; mOPop[1]->SetValueStr(sdum);
mOPop[1]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);

  cpy += bsy+spy;
mOPop[2] = new PIOptMenu(this, "optmen-h2d-3",2*bsx,bsy,cpx,cpy);
mOPop[2]->AppendItem("Black&White", 6301);
mOPop[2]->AppendItem("Grey32"    , 6302);
mOPop[2]->AppendItem("GreyInv32" , 6303);
mOPop[2]->AppendItem("ColRJ32"   , 6304);
mOPop[2]->AppendItem("ColBR32"   , 6305);
mOPop[2]->AppendItem("ColRV32"   , 6306);
mOPop[2]->AppendItem("Grey128"   , 6307);
mOPop[2]->AppendItem("GreyInv128", 6308);
mOPop[2]->AppendItem("ColRJ128"  , 6309);
mOPop[2]->AppendItem("ColBR128"  , 6310);
mOPop[2]->AppendItem("Col16"     , 6311);
sdum = "Black&White"; mOPop[2]->SetValueStr(sdum);
mOPop[2]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);

// Labels et zone de saisie texte
  cpy += 2*(bsy+spy);
mLab[0] = new PILabel(this, "     Dyn: ",bsx,bsy,cpx,cpy); 
mLab[0]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
mText[0] = new PIText(this, "Dynamique" ,int(2.5*bsx),bsy,cpx+bsx+spx,cpy);
mText[0]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
  cpy += bsy+spy;
mLab[1] = new PILabel(this, "    Frac: ",bsx,bsy,cpx,cpy);
mLab[1]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
mText[1] = new PIText(this, "Fraction"  ,int(2.5*bsx),bsy,cpx+bsx+spx,cpy);
mText[1]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
  cpy += bsy+spy;
mLab[2] = new PILabel(this, " LogScal: ",bsx,bsy,cpx,cpy);
mLab[2]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
mText[2] = new PIText(this, "LogScale"  ,int(2.5*bsx),bsy,cpx+bsx+spx,cpy);
mText[2]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
SetText();

// Labels et curseur mobile
cpy += bsy+spy;
mLab[3] = new PILabel(this, "   PerPt: ",bsx,bsy,cpx,cpy+0.25*bsy);
mLab[3]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
mPScal = new PIScale(this,"FracPoints",6401,kSDirLtoR
                        ,int(2.5*bsx),1.25*bsy,cpx+bsx+spx,cpy);
mPScal->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
mPScal->SetMinMax(0,100);
int imfp = mFPoints*100.f; mPScal->SetValue(imfp);

// Boutons
  cpx = 2*bsx+5*spx, cpy = 2*spy;
mBut[0] = new PIButton(this, "Apply",  6001,bsx,bsy,cpx,cpy);
mBut[0]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
  cpy += bsy+spy;
mBut[1] = new PIButton(this, "Dismiss",6002,bsx,bsy,cpx,cpy);
mBut[1]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
  cpy += bsy+spy;
mBut[2] = new PIButton(this, "Get"  ,  6003,bsx,bsy,cpx,cpy);
mBut[2]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
  cpy += bsy+spy;
mBut[3] = new PIButton(this, "Print",  6004,bsx,bsy,cpx,cpy);
mBut[3]->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
// FinishCreate();
}

//++
H2WinArg::~H2WinArg()
//
//	Destructeur.
//--
{
int i;
if(dbg) printf("H2WinArg::~H2WinArg %lx\n",(long)this);
for(i=0;i<3;i++) delete mOPop[i];
for(i=0;i<4;i++) delete mBut[i];
for(i=0;i<4;i++) delete mLab[i];
for(i=0;i<3;i++) delete mText[i];
delete mPScal;
}

//++
void H2WinArg::SetText()
//
//	Gestion des fenetres de saisie de texte.
//--
{
string sdum;
char str[256];
sprintf(str,"%g %g",mHMin,mHMax);
mText[0]->SetText(str);
sprintf(str,"%g %g",mFracMin,mFracMax);
mText[1]->SetText(str);
sprintf(str,"%g",mLogScale);
mText[2]->SetText(str);

if(mTypDisp==0)      { sdum="Carres Var.";   mOPop[0]->SetValueStr(sdum);}
else if(mTypDisp==1) { sdum=".....";         mOPop[0]->SetValueStr(sdum);}
else if(mTypDisp==2) { sdum=".+12..Z*";      mOPop[0]->SetValueStr(sdum);}
else if(mTypDisp==3) { sdum="Carres Pleins"; mOPop[0]->SetValueStr(sdum);}

if(mTypScal==0)      { sdum="Lineaire"; mOPop[1]->SetValueStr(sdum);}
else if(mTypScal==1) { sdum="Log10";    mOPop[1]->SetValueStr(sdum);}

if(!mFgCol)                       { sdum="Black&White";mOPop[2]->SetValueStr(sdum);}
else {
  if(mCmap==CMAP_GREY32)          { sdum="Grey32";     mOPop[2]->SetValueStr(sdum);}
  else if(mCmap==CMAP_GREYINV32)  { sdum="GreyInv32";  mOPop[2]->SetValueStr(sdum);}
  else if(mCmap==CMAP_COLRJ32)    { sdum="ColRJ32";    mOPop[2]->SetValueStr(sdum);}
  else if(mCmap==CMAP_COLBR32)    { sdum="ColBR32";    mOPop[2]->SetValueStr(sdum);}
  else if(mCmap==CMAP_COLRV32)    { sdum="ColRV32";    mOPop[2]->SetValueStr(sdum);}
  else if(mCmap==CMAP_GREY128)    { sdum="Grey128";    mOPop[2]->SetValueStr(sdum);}
  else if(mCmap==CMAP_GREYINV128) { sdum="GreyInv128"; mOPop[2]->SetValueStr(sdum);}
  else if(mCmap==CMAP_COLRJ128)   { sdum="ColRJ128";   mOPop[2]->SetValueStr(sdum);}
  else if(mCmap==CMAP_COLBR128)   { sdum="ColBR128";   mOPop[2]->SetValueStr(sdum);}
  else if(mCmap==CMAP_COL16)      { sdum="Col16";      mOPop[2]->SetValueStr(sdum);}
}

if(dbg)printf("H2WinArg::SetText\n");
}

//++
void H2WinArg::GetText()
//
//	Gestion des fenetres de saisie de texte.
//--
{
sscanf(mText[0]->GetText().c_str(),"%g %g",&mHMin,&mHMax);
sscanf(mText[1]->GetText().c_str(),"%g %g",&mFracMin,&mFracMax);
sscanf(mText[2]->GetText().c_str(),"%g",&mLogScale);
if(dbg) printf("H2WinArg::GetText\n");
}

//++
void H2WinArg::SetPIH2DWdg(PIH2DWdg* h2wdg)
//
//	Connexion du widget de representation d'un histogramme 2D
//	avec la fenetre de gestion des parametres.
//--
{
mH2Wdg = h2wdg;
if(dbg) printf("H2WinArg::SetPIH2DWdg mH2Wdg = %lx\n",(long)mH2Wdg);
}

//++
void H2WinArg::Process(PIMessage msg, PIMsgHandler* sender, void*)
//
//	Gestions des messages.
//--
{
if(dbg) printf("PIH2DWdg::Process(%d-%d , %lx ...) \n"
              ,(int)UserMsg(msg),(int)ModMsg(msg), (long)sender);

if(!mH2Wdg) return;
PIHisto2D* mpih = mH2Wdg->GetPIHisto();
if(!mpih) return;

int opt = UserMsg(msg);
     if (opt == 6101) { mTypDisp = 0; }
else if (opt == 6102) { mTypDisp = 1; }
else if (opt == 6103) { mTypDisp = 2; }
else if (opt == 6104) { mTypDisp = 3; }

else if (opt == 6201) { mTypScal = 0; }
else if (opt == 6202) { mTypScal = 1; }

else if (opt == 6301) { mFgCol = false; }
else if (opt == 6302) { mFgCol = true;  mCmap = CMAP_GREY32; }
else if (opt == 6303) { mFgCol = true;  mCmap = CMAP_GREYINV32; }
else if (opt == 6304) { mFgCol = true;  mCmap = CMAP_COLRJ32; }
else if (opt == 6305) { mFgCol = true;  mCmap = CMAP_COLBR32; }
else if (opt == 6306) { mFgCol = true;  mCmap = CMAP_COLRV32; }
else if (opt == 6307) { mFgCol = true;  mCmap = CMAP_GREY128; }
else if (opt == 6308) { mFgCol = true;  mCmap = CMAP_GREYINV128; }
else if (opt == 6309) { mFgCol = true;  mCmap = CMAP_COLRJ128; }
else if (opt == 6310) { mFgCol = true;  mCmap = CMAP_COLBR128; }
else if (opt == 6311) { mFgCol = true;  mCmap = CMAP_COL16; }

else if (opt == 6401) mFPoints = mPScal->GetValue()/100.;

else if (opt==6001) {
  GetText();
  mpih->UseColors(mFgCol, mCmap);
  mpih->UseScale(mTypScal,mLogScale);
  mpih->UseDisplay(mTypDisp,mFPoints);
  mpih->UseDyn(mHMin,mHMax);
  mpih->UseFrac(mFracMin,mFracMax);
  mH2Wdg->Refresh();  // On rafraichit le dessin (tout le PIScDrawWdg)
}
else if (opt==6002) {
  this->Hide();
}
else if (opt==6003) {
  mFgCol    = mpih->Color();
  mCmap     = mpih->ColMap();
  mTypScal  = mpih->TypScale();
  mTypDisp  = mpih->TypDisplay();
  mFPoints  = mpih->FPoints();
  mHMin     = mpih->HMin();
  mHMax     = mpih->HMax();
  mFracMin  = mpih->FMin();
  mFracMax  = mpih->FMax();
  mLogScale = mpih->LogScale();
  SetText();
}
else if (opt==6004) {
  mpih->Print(2);
}

if(dbg) {
  printf("H2WinArg::Process opt=%d col=%d,%d scal=%d disp=%d npt=%g\n"
        ,opt,(int) mFgCol,(int) mCmap,mTypScal,mTypDisp,mFPoints);
  printf("                  min,max= %g,%g frac= %g,%g logsc= %g\n"
        ,mHMin,mHMax,mFracMin,mFracMax,mLogScale);
}

}
