// This may look like C code, but it is really -*- C++ -*-
// Module PI : Peida Interactive  - Zone/Stack Layout
// PIStackLayout , PIZone Layout , PIStackWindow , PIZoneWindow
//                             R. Ansari  08/98

#include <stdio.h>

#include "pistzwin.h"
#include "psfile.h"

// -------------- Classe PIStackLayout --------------

//++
// Class	PIStackLayout
// Lib		PI
// include	pistzwin.h
//
//	Classe de gestionnaire de "PIWdg" dans un conteneur avec un seul 
//	"PIWdg" visible à un moment donné. Permet d'empiler plusieurs
//	objet dans une fenêtre, et passer de l'un à l'autre.
//--
//++
// Links	Parent
// PILayoutMgr
//--

//++
// Titre	Constructeur, méthodes
//--
//++
// PIStackLayout()
// 	Constructeur
// PIWdg*  CurrentWdg() 
//	Retourne l'objet "PIWdg" visible au moment de l'appel.
// int NumCurrentWdg()
//	Retourne le numéro de l'objet "PIWdg" visible au moment de l'appel.
// void  DispNext()
//	Affiche l'objet "PIWdg" suivant.
// void  DispWdgNum(int n)
//	Affiche l'objet "PIWdg" numéro "n".
//--

/* --Methode-- */
PIStackLayout::PIStackLayout()
	: PILayoutMgr()
{
mCurdisp = -1;
}

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

/* --Methode-- */
void PIStackLayout::ChildAdd(PIWdg* child)
{
int k;
for(k=0; k<NbChilds(); k++) GetChild(k)->UnManage();
PILayoutMgr::ChildAdd(child);
child->Manage();
mCurdisp = NbChilds()-1;
return;
}

/* --Methode-- */
void PIStackLayout::ChildDel(PIWdg* child)
{
int k;
for(k=0; k<NbChilds(); k++) GetChild(k)->UnManage();
PILayoutMgr::ChildDel(child);
if (NbChilds() > 0) {
  mCurdisp--;
  if (mCurdisp < 0)  mCurdisp = 0;
  if (mCurdisp > NbChilds()) mCurdisp = NbChilds()-1; 
  GetChild(mCurdisp)->Manage();
  }
else mCurdisp = -1;
return;
}

/* --Methode-- */
void PIStackLayout::DispNext()
{
if (NbChilds() < 1) return;
int n = (mCurdisp+1)%NbChilds();
DispWdgNum(n);
}

/* --Methode-- */
void PIStackLayout::DispWdgNum(int n)
{
if ( (n < 0) || (n >= NbChilds()) )  return;
for(int k=0; k<NbChilds(); k++) GetChild(k)->UnManage();
mCurdisp = n;
GetChild(mCurdisp)->Manage();
return;
}


// -------------- Classe PIStackWindow --------------

// Fonction de l'objet PIPeriodic de PIStackWindow
static void myadperpact(void* a);

void myadperpact(void* a)
{
((PIStackWindow*)a)->DispNext();
}

//++
// Class	PIStackWindow
// Lib		PI
// include	pistzwin.h
//
//	Classe de fenêtre ("PIWindow") avec le "PIStackLayout".
//	Le "PILayoutMgr" ne peut être changé.
//--
//++
// Links	Parent
// PIWindow
//--
//++
// Links	Voir aussi
// PIStackLayout
//--
//++
// Titre	Constructeur, méthodes
//--
//++
// PIStackWindow(PIMsgHandler* par, const char* nom, PIWindowKind k=PIWK_normal, int sx=100, int sy=100, int px=0, int py=0)
// 	Constructeur - identique à celui de "PIWindow"
// void  DispNext()
//	Affichage du "PIWdg" suivant.
// PIWdg* CurrentWdg()
//	Retourne l'objet "PIWdg" courant.
// void  StartAutoDisp(int dtms=1000)
//	Démarre  l'affichage cyclique automatique avec l'intervalle en temps 
//	"dtms" spécifié en millisecondes.
// void  StopAutoDisp()
//	Arrête l'affichage cyclique automatique.
// void  PSPrint(PSFile *psf, int ofx=0, int ofy=0)
//	Rajoute tous les "PIWdg" associés à la fenêtre à l'objet
//	"PSFile" (fichier PostScript), un objet par page.
//--

/* --Methode-- */
PIStackWindow::PIStackWindow(PIMsgHandler* par, const char* nom, PIWindowKind k,
                             int sx, int sy, int px, int py)
        : PIWindow(par, nom, k, sx, sy, px, py) , mPerad(1)
{
mPerad.SetAction(myadperpact, this);
delete layout;
layout = new PIStackLayout;
layout->SetContainer(this); 
} 


/* --Methode-- */
PIStackWindow::~PIStackWindow()
{
mPerad.Stop();
Hide();
}

/* --Methode-- */
void PIStackWindow::SetLayoutMgr(PILayoutMgr*)
{
fprintf(stderr, "PIStackWindow::SetLayoutMgr() - LayoutMgr cannot be changed \n");
return;
}

/* --Methode-- */
void PIStackWindow::PSPrint(PSFile *psf, int ofx, int ofy, double scale_x, double scale_y)
{
if (!psf) return;
int k;
for(k=0; k<NbChilds(); k++) { 
  psf->NewPage((double)XSize()*scale_x, (double)YSize()*scale_y,PI_Auto);
  GetChild(k)->PSPrint(psf, ofx, ofy, scale_x, scale_y);
  }
}


/* --Methode-- */
void PIStackWindow::StartAutoDisp(int dtms)
{
mPerad.SetIntervalms(dtms);
mPerad.Start();
}

/* --Methode-- */
void PIStackWindow::StopAutoDisp()
{
mPerad.Stop();
}

//-------------------- Classe PIZoneLayout ------------------------------
//++
// Class	PIZoneLayout
// Lib		PI
// include	pistzwin.h
//
//	Classe de gestionnaire de "PIWdg" dans un conteneur, 
//	divisé en cellule horizotale-verticale.
//	En cas d'ajout d'un objet dans une cellule déjà occupée,
//	l'objet est supprimé si "SetAutoDelChilds(true)", 
//	sinon "UnManage()" est appelé pour cet objet.
//--
//++
// Links	Parent
// PILayoutMgr
//--

//++
// Titre	Constructeur, méthodes
//--
//++
// PIZoneLayout(int nzx, int nzy)
// 	Constructeur. Subdivision en "nzx" cellules horizontales,
//	"nzy" cellules verticales.
// void SetZone(int nzx, int nzy)
//	Modification du découpage en cellules.
// void  NbZone(int& nzx, int& nzy)
//	Retourne le nombre de cellules verticale-horizontale.
// PIWdg* NextChildPosSize(int& px, int& py, int& sx, int& sy)
//	Retourne la position et la taille d'un eventuel objet "PIWdg"
//	ajouté. Retourne le "PIWdg" actuellement dans cette cellule.
//-- 

/* --Methode-- */
PIZoneLayout::PIZoneLayout(int nzx, int nzy)
	: PILayoutMgr()
{
mZWdg = NULL;
SetZone(nzx, nzy);
}

/* --Methode-- */
PIZoneLayout::~PIZoneLayout()
{
delete[] mZWdg;
}


/* --Methode-- */
void PIZoneLayout::SetZone(int nzx, int nzy)
{
int i;
if (mZWdg) {
  for(i=0; i<mZx*mZy; i++) 
    if (mZWdg[i]) delete mZWdg[i];  
  delete[]  mZWdg;
  }

if (nzx < 1) nzx = 1;
if (nzy < 1) nzy = 1;
if (nzx > 50) nzx = 50;
if (nzx > 50) nzx = 50;
mZx = nzx;  mZy = nzy;   mZc = 0;

mZWdg = new PIWdg*[nzx*nzy];
for(i=0; i<mZx*mZy; i++) mZWdg[i] = NULL; 
}


/* --Methode-- */
void PIZoneLayout::ChildAdd(PIWdg * child)
{
if (!child) return;
int nx = mZc%mZx;
int ny = mZc/mZx;
PILayoutMgr::ChildAdd(child);
child->SetBinding(PIBK_free,PIBK_free,PIBK_free, PIBK_free);
int sx = mCont->XSize()/mZx;
int sy = mCont->YSize()/mZy;
child->SetPos(nx*sx, ny*sy);
child->SetSize(sx, sy);
child->SetBinding(PIBK_elastic,PIBK_elastic,PIBK_elastic, PIBK_elastic);
child->LockBinding();
//  Il faut faire le delete a cet endroit, sinon probleme avec widget motif XmForm  Reza 18/08/98
if (mZWdg[mZc])  { 
  if (mACSup) delete mZWdg[mZc]; 
  else mZWdg[mZc]->UnManage();
  }
mZWdg[mZc] = child;
mZc = (mZc+1)%(mZx*mZy);
}

/* --Methode-- */
void PIZoneLayout::ChildDel(PIWdg * child)
{
if (!child)  return;
int k;
for(k=0; k<mZx*mZy; k++) 
  if (mZWdg[k] == child) mZWdg[k] = NULL;  
PILayoutMgr::ChildDel(child);
return;
}

/* --Methode-- */
void PIZoneLayout::NbZone(int& nzx, int& nzy)
{
nzx = mZx;   nzy = mZy;
}

/* --Methode-- */
PIWdg* PIZoneLayout::NextChildPosSize(int& px, int& py, int& sx, int& sy)
{
sx = mCont->XSize()/mZx;
sy = mCont->YSize()/mZy;
int nx = mZc%mZx;
int ny = mZc/mZx;
px = nx*sx;  py = ny*sy;
return ((PIWdg*)mZWdg[mZc]);
}


//-------------------- Classe PIZoneWindow ------------------------------
//++
// Class	PIZoneWindow
// Lib		PI
// include	pistzwin.h
//
//	Classe de fenêtre ("PIWindow") avec le "PIZoneLayout".
//	Le "PILayoutMgr" ne peut être changé.
//--
//++
// Links	Parent
// PIWindow
//--
//++
// Links	Voir aussi
// PIZoneLayout
//--
//++
// Titre	Constructeur, méthodes
//--
//++
// PIZoneWindow(PIMsgHandler* par, const char* nom, PIWindowKind k=PIWK_normal, -
//              int nzx=1, int nzy=1, int sx=100, int sy=100, int px=0, int py=0)
// 	Constructeur avec spécification de nombre de cellules horizontal "nzx", vertical "nzy".
// void  SetZone(int nzx, int nzy)
//	Modification du découpage en cellules.
// void NbZone(int& nzx, int& nzy)
//	Retourne le nombre de cellules verticale-horizontale.
// PIWdg* NextChildPosSize(int& px, int& py, int& sx, int& sy)
//	Appel à " PIZoneLayout::NextChildPosSize(...) "
//--

/* --Methode-- */
PIZoneWindow::PIZoneWindow(PIMsgHandler* par, const char* nom, PIWindowKind k,
                           int nzx, int nzy, int sx, int sy, int px, int py)
        : PIWindow(par, nom, k, sx, sy, px, py)
{
delete layout;
layout = new PIZoneLayout(nzx, nzy);
layout->SetContainer(this); 
}

/* --Methode-- */
PIZoneWindow::~PIZoneWindow()
{
Hide();
}

/* --Methode-- */
void PIZoneWindow::SetLayoutMgr(PILayoutMgr*)
{
fprintf(stderr, "PIZoneWindow::SetLayoutMgr() - LayoutMgr cannot be changed \n");
return;
}

