// Module PI : Peida Interactive     PICMapView
// Visualisation de table de couleur     R. Ansari  07/98
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include "sopnamsp.h"
#include "picmapview.h"
#include "strutil.h"
#include <math.h>
#include <iostream>

//++
// Class	PICMapView
// Lib		PI
// include	picmapview.h
//
//   	Classe permettant la visualisation d'une table de couleur.
//--
//++
// Links	Parents
// PIBaseWdg
//--
//++
// Links	Voir aussi
// PIColorMap
//--

//++
// Titre	Constructeur
//--
//++
//  PICMapView(PIContainerGen *par, const char *nom, int sx=256, int sy=10, int px=0, int py=0);
//	Constructeur - Le choix d'affichage (vertical ou horizontal) dépend
//	du rapport des tailles "sx", "sy"
//--


/* --Methode-- */
PICMapView::PICMapView(PIContainerGen *par, const char *nom,
                       int sx, int sy, int px, int py) 
: PIBaseWdg(par, nom, sx, sy, px, py)

{
  cmap = NULL;
  vmin = 1.;   vmax = -1.; 
}


/* --Methode-- */
PICMapView::~PICMapView()
{
  if (cmap) delete cmap;
}



//++
// Titre	Méthodes
//--
//++
// long  kind()
//	Retourne PICMapView::ClassId .
// void   SetColMap(PIColorMap* cmp=NULL, double min=1., double max=-1., bool refr=true)
//	Choix de la table de couleur et valeurs min et max. Si "refr==true",
//	la méthode "Refresh()" est appelée.
// void  SetColMapId(CMapId cmapid, double min=1., double max=-1., bool refr=true)
//	Choix de la table de couleur en utilisant le "CMapId" et 
//	définition des valeurs min et max. Si "refr==true",
//	la méthode "Refresh()" est appelée.
//--
 
/* --Methode-- */
void PICMapView::SetColMap(PIColorMap* cmp, double min, double max, bool refr)
{
  if (cmp == NULL)   { 
    if (cmap) delete cmap;
    cmap = NULL;
    vmin = 1.;  vmax = -1.;
    if (refr)  Refresh();  
    return;
    }
  if ( cmap && (cmp->Type() == cmap->Type()) && (cmp->Type() != CMAP_OTHER)
       && (cmp->IsColorIndexReversed() == cmap->IsColorIndexReversed())
       && (fabs(vmin-min) < 1.e-69)  && (fabs(vmax-max) > -1.e-69) )  { 
    if (refr)  Refresh();      
    return;
  }
  if (cmap) delete cmap;
  cmap = new PIColorMap(*cmp);
  vmin = min;  vmax = max;
  if (refr)  Refresh();  
  return;
}

/* --Methode-- */
void PICMapView::SetColMapId(CMapId cmapid, bool revidx, double min, double max, bool refr)
{
  if ( cmap && (cmapid == cmap->Type()) && (cmapid != CMAP_OTHER) &&
       (cmap->IsColorIndexReversed() == revidx) &&
       ((vmin-min) < 1.e-69) &&  ((vmin-min) > -1.e-69) &&
       ((vmax-max) < 1.e-69) &&  ((vmax-max) > -1.e-69) )  { 
    if (refr)  Refresh();      
    return;
  }
  if (cmap) delete cmap;
  cmap = new PIColorMap(cmapid);
  cmap->ReverseColorIndex(revidx);
  vmin = min;  vmax = max;
  if (refr)  Refresh();  
  return;
}


/* --Methode-- */
void PICMapView::Draw(PIGraphicGen* g, int /*x0*/, int /*y0*/, int /*dx*/, int /*dy*/)
{
  if (!cmap) { 
    EraseWindow(0, 0, XSize(), YSize());
    return;
    }
  // On presente la table de couleur verticalement si SizeY > SizeX 
  // ou horizontale  si SizeX > SizeY

  int sx = XSize(); 
  int sy = YSize(); 

  int k;
  // On limite le nombre de carres de couleurs traces, si trop de couleur ...
  int dk = cmap->NCol()/128;
  if (dk<1) dk=1;
  if (sx > sy) {    // horizontal
    int xc, dx;
    xc = 0;
    for(k=0; k<cmap->NCol(); k+=dk) {
      dx = dk*(sx-xc)/(cmap->NCol()-k);
      g->SelForeground((*cmap), k);
      g->DrawFBox(xc, 0, dx+1, sy);
      xc += dx;
    }
  }
  else  {    // vertical
    int yc, dy;
    yc = sy;
    for(k=0; k<cmap->NCol(); k+=dk) {
      dy = dk*yc/(cmap->NCol()-k);
      yc -= dy;
      g->SelForeground((*cmap), k);
      g->DrawFBox(0, yc, sx, dy+1);
    }
  }
  if (vmin > vmax)   return;

  if ( (cmap->Type() == CMAP_GREY32) || (cmap->Type() == CMAP_GREYINV32) ||
       (cmap->Type() == CMAP_GREY128) || (cmap->Type() == CMAP_GREYINV128) || 
       (cmap->Type() == CMAP_GREEN32) )  g->SelForeground(PI_Red);
  else g->SelForeground(PI_Green);

  if (sx > sy) {    // horizontal
    int fsz = (sy < 20) ? sy-6 : 14;
    g->SelFontSzPt(fsz, PI_BoldFont);
    char buff[32];
    double av;
    av = fabs(vmin);
    if ( (av < 1.e6) && (av > 1.e-3) )  sprintf(buff, "%.2f", vmin);
    else sprintf(buff, "%8.4g", vmin);
    g->DrawString(4, sy-4, buff);
    av = fabs(vmax);
    if ( (av < 1.e6) && (av > 1.e-3) )  sprintf(buff, "%.2f", vmax);
    else sprintf(buff, "%8.4g", vmax);
    g->DrawString(sx-4-(int)g->CalcStringWidth(buff), sy-4, buff);
    } 
  else {   // vertical 
    int fsz = (sx < 64) ? sx/4 : 14;
    g->SelFontSzPt(fsz, PI_BoldFont);
    char buff[32];
    double av;
    av = fabs(vmin);
    if ( (av < 1.e6) && (av > 1.e-3) )  sprintf(buff, "%.2f", vmin);
    else sprintf(buff, "%8.4g", vmin);
    g->DrawString(4, sy-4, buff);
    av = fabs(vmax);
    if ( (av < 1.e6) && (av > 1.e-3) )  sprintf(buff, "%.2f", vmax);
    else sprintf(buff, "%8.4g", vmax);
    int fa, fd;
    g->DrawString(4, g->GetFont().GetFontHeight(fa,fd)+4, buff);
    } 
    
  return;
}

//++
// Class        PICMapDrawer
// Lib          PI
// include      picmapview.h
//
//      Classe de traceur de colormap 
//--
//++
// Links        Parents
// PIDrawer
//--
//++


/* --Methode-- */
PICMapDrawer::PICMapDrawer(bool fgvert)
  : fgvert_(fgvert), fgtext_(false), cmapp(NULL), bornes_(5)   
{
  SetLimits(0.,1.,0.,1., kAxeDirLtoR, kAxeDirDownUp);
  SetColMapId(CMAP_GREY32);
}

/* --Methode-- */
PICMapDrawer::~PICMapDrawer()
{
}

/* --Methode-- */
void PICMapDrawer::SetBornes(LUT& lut)
{
  fgtext_=true;  
  bornes_[0]=lut.Min();   bornes_[4]=lut.Max(); 
  bornes_[1]=lut.Borne((lut.NCol()-2)/4);
  bornes_[2]=lut.Borne((lut.NCol()-2)/2);
  bornes_[3]=lut.Borne(3*(lut.NCol()-2)/4);
  return;
}

/* --Methode-- */
void PICMapDrawer::SetBornes(double min, double max)
{
  fgtext_=true;  
  bornes_[0]=min;   bornes_[4]=max; 
  bornes_[1]=min+(max-min)*0.25; 
  bornes_[2]=min+(max-min)*0.5; 
  bornes_[3]=min+(max-min)*0.75; 
  return;
}

/* --Methode-- */
void PICMapDrawer::Draw(PIGraphicUC* g, double /*xmin*/, double /*ymin*/, 
                        double /*xmax*/, double /*ymax*/)
{
  PIColorMap* cmp=cmapp;
  PIColorMap cmapi(cmapid_);
  if (cmp==NULL)  cmp=&cmapi;
  PIColorMap& cmap=(*cmp);

  //  cout << " *DBG*PICMapDrawer::Draw() Sz:" << BWdgXSize() << "," << BWdgYSize() 
  //     << " Pos:" << BWdgXPos() << "," << BWdgYPos() << endl; 
  // On limite le nombre de carres de couleurs traces, si trop de couleur ...
  PIPixColIdx pixc;
  if (fgvert_) {   // vertical
    pixc.AllocateByte(0.25*BWdgXSize(), BWdgYSize());
    for(int j=0; j<pixc.YSize(); j++)  {
      int ci = j*cmap.NCol()/pixc.YSize();
      int jrev=pixc.YSize()-j-1;
      for(int i=0; i<pixc.XSize(); i++) pixc.GetByte(i,jrev)=(unsigned char)ci;
    }
    g->DrawPixmap(0.,1.,pixc, cmp);
  }
  else {    // horizontal
    pixc.AllocateByte(BWdgXSize(), 0.25*BWdgYSize());
    for(int i=0; i<pixc.XSize(); i++)  {
      int ci = i*cmap.NCol()/pixc.XSize();
      for(int j=0; j<pixc.YSize(); j++) pixc.GetByte(i,j)=(unsigned char)ci;
    }
    g->DrawPixmap(0.,0.25,pixc, cmp);
  }


  if (!fgtext_) return;
  char buff[32];
  double ps[5]={0.025,0.25,0.5,0.75,0.975};
  //  g->SelForeground(PI_White);
  for(int k=0; k<5; k++) {
    sprintf(buff,"%6.2lg",bornes_[k]);
    strip(buff,'B',' ');
    if (fgvert_) {   // vertical
      g->DrawLine(0.25,ps[k],0.35,ps[k]);
      g->DrawString(0.7, ps[k], buff, PI_TextDirectionVerticalUp|PI_HorizontalCenter|PI_VerticalCenter);
    }
    else {   // horizontal 
      g->DrawLine(ps[k],0.25,ps[k],0.35);
      g->DrawString(ps[k], 0.7, buff, PI_VerticalCenter|PI_HorizontalCenter);
    }
  }
  return;
}


