//  Classe de base pour les conteneurs de PIWdg pour
//  programmes graphiques interactives
//
//                  E.Aubourg , R. Ansari  96 - 98
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include <stdio.h>

#include "picontainergen.h"

//++
// Class	PIContainer
// Lib		PI
// include	picontainergen.h
//
//	Classe conteneur gérant un ensemble d'objets "PIWdg". Cette classe 
//	organise la hiérarchie des objets "PIWdg" et donc aussi des "PIMsgHandler",
//	contrôle la géométrie des objets "PIWdg" contenus, ainsi que leur 
//	visibilité et activité. Le positionnement initial est controle par
//	un objet *PILayoutMgr* qui peut eventuellement modifier la postion
//	ou la taille de l'objet "PIWdg" ajouté. Les attributs d'attachement
//	de l'objet ("PIWdg::SetBinding()") contrôle le repositionnement
//	lors du changement de taille du "PIContainer".
//	La classe "PIContainer" est une des 
//	classes de PI qui ont une implementation dépendante du systeme utilisé
//	(Mac, XWindow, ...). La classe "PIContainerGen" est la classe qui
//	définit l'interface, et ne pas doit être instanciée directement
//	(Méthodes virtuelles pures). Les objets instanciés sont de la 
//	classes "PIContainer" et le fichier entête correspondant est "PICONT_H"
//	défini dans "pisysdep.h"
//--
//++
// Links	Parents
// PIWdg
//--
//++
// Links	Voir aussi
// PILayoutMgr
//--
//++
// Titre	Constructeur
//--
//++
// PIContainer(PIContainerGen *par, const char *nom, int sx, int sy, int px, int py)
//	Création d'un objet "PIContainer" dans le conteneur parent "par", de
//	taille "sx,sy", se trouvant à la position "px,py" avec le nom "nom".
//	Tous les widgets fils sont détruits (delete) par le destructeur
//	(voir "SetAutoDelChilds()")
// long kind()
//	Renvoie le type de la classe de l'objet ("=PIContainerGen::ClassId") pour cette classe.
//--
//++
// Titre	Méthodes
//--
//++
// void SetLayoutMgr(PILayoutMgr* nlay)
//	Permet de changer le gestionnaire de positions ("PILayoutMgr") du conteneur,
//	et donc la stratégie de positionnement des objets "PIWdg" fils. 
//	le LayoutMgr par défaut n'applique aucune contrainte sur la position
//	ou la taille des objets ajoutés.
//	Cette méthode ne peut être appelé que pour un conteneur vide (sans PIWdg fils).
//	Il est conseillé de l'appeler juste après la création du "PIContainer"
// PILayoutMgr* GetLayoutMgr()
//	Retourne le gestionnaire de positions/tailles du conteneur.
// void Show()
//	Rend l'objet visible à l'écran. Tous les objets "PIWdg" contenus et qui sont dans 
//	l'état actif sont visibles.
// void Hide()
//	Rend l'objet et tous les objets contenus invisibles.
// void  PSPrint(PSFile *psf, int ofx=0, int ofy=0)
//	Appelle la méthode "PSPrint()" pour tous les objets contenus.
// void  SetAutoDelChilds(bool ad = true)
//	Contrôle le comportement de l'objet conteneur vis à vis des objets
//	contenus lors de la destruction. si "ad=true", les objets contenus 
//	sont détruits lors de l'appel du destructeur de l'objet conteneur. 
// int  NbChilds()
//	Retourne le nombre de "PIWdg" contenus.
// PIWdg* GetChild(int n)
//	Retourne le "PIWdg" numéro "n" (0..NbChilds()-1) 
//--
//++
// Titre 	Méthodes particulières
//	Les méthodes ci-dessous ne doivent pas être appelées directement.
//--
//++
// void ChildAdd(PIWdg* child)
//	Méthode qui est appelée lors de l'attachement d'un nouvel objet (création)
//	Appelle la méthode correspondante du "PILayoutMgr"
// void ChildAdd(PIWdg* child)
//	Méthode qui est appelée lors du détachement d'un objet (destruction)
//	Appelle la méthode correspondante du "PILayoutMgr"	
//--


/* --Methode-- */
PIContainerGen::PIContainerGen(PIContainerGen *par, const char *nom, 
                               int sx, int sy, int px, int py)
: PIWdg(par, nom, sx, sy, px, py)  
{
stvis = false;
stfcr = false;
layout = new PILayoutMgr;
layout->SetContainer(this); 
}


/* --Methode-- */
PIContainerGen::~PIContainerGen()
{
delete layout;
}

/* --Methode-- */
void PIContainerGen::SetLayoutMgr(PILayoutMgr* nlay)
{
if (nlay == NULL) return;
if (NbChilds() > 0) {
  fprintf(stderr, "PIContainerGen::SetLayoutMgr()/ Error! Container has childs (N = %d) \n", NbChilds()); 
  return;
  }
delete layout;
layout = nlay;
layout->SetContainer(this); 
}

/* --Methode-- */
void PIContainerGen::PSPrint(PSFile *psf, int ofx, int ofy, double scale_x, double scale_y)
{
int i;
if (!psf)  return;
if (!Visible())  return;
for(i=0; i<NbChilds(); i++)  
  GetChild(i)->PSPrint(psf, ofx+XPos(), ofy+YPos(), scale_x, scale_y); 
return;
}

/* --Methode-- */
void PIContainerGen::Show()
{
stvis = true;
Manage();
return;
}

/* --Methode-- */
void PIContainerGen::Hide()
{
stvis = false;
UnManage();
return;
}

/* --Methode-- */
bool PIContainerGen::Visible()
{
if (Parent())  return(stvis && Parent()->Visible());
else return(stvis && IsVisible());
}

/* --Methode-- */
void PIContainerGen::ChildAdd(PIWdg* child)
{
layout->ChildAdd(child);
// Reza 13/10/98 : il faut que child->FinishCreate() 
// soit appele pour les PIWdg ajoute quand le  container est deja affiche et son FinishCreate() appele
if (stfcr)  child->FinishCreate(); 
return;
}

/* --Methode-- */
void PIContainerGen::ChildDel(PIWdg* child)
{
layout->ChildDel(child);
}

/* --Methode-- */
int PIContainerGen::NbChilds()
{
return(layout->NbChilds());
}

/* --Methode-- */
PIWdg* PIContainerGen::GetChild(int n)
{
return(layout->GetChild(n));
}

/* --Methode-- */
void PIContainerGen::SetAutoDelChilds(bool ad)
{
layout->SetAutoDelChilds(ad) ;
}


/* --Methode-- */
void PIContainerGen::FinishCreate()
{
if (stfcr)  return;
PIWdg::FinishCreate();    
int k;
for(k=0; k<NbChilds(); k++)  GetChild(k)->FinishCreate();
stfcr = true;
}


// ------------------------------------------------------------------
//  Classe PILayoutMgr (Gestionnaire de positions/tailles PIWdg fils
// ------------------------------------------------------------------
//++
// Class	PILayoutMgr
// Lib		PI
// include	picontainergen.h
//
//	Classe de gestionnaire de positions/tailles initiales des "PIWdg"
//	fils pour les "PIContainer".
//	La classe de base n'impose aucune contrainte sur les positions/tailles.
//--
//++
// Links	Voir
// PIContainer
//--

//++
// Titre	Constructeur, méthodes
//--
//++
// PILayoutMgr()
//	Constructeur
// void ChildAdd(PIWdg* child)
//	Méthode appelé lors de l'ajout d'un nouveau "PIWdg" au conteneur.
// void ChildDel(PIWdg* child)
//	Méthode appelé lors de la suppression d'un "PIWdg"
// int  NbChilds() 
//	Nombre de "PIWdg" gérés.
// PIWdg* GetChild(int n)
//	Retourne l'objet "PIWdg" numéro "n"
//--

#define NCHALGRP 8

/* --Methode-- */
PILayoutMgr::PILayoutMgr()
{
mNCh = 0;
mACSup = false;   // Pas de Suppression automatique des widgets fils au delete
mPaSup = false;
mChilds = new (PIWdg* [NCHALGRP]);
mMxCh = NCHALGRP;
mCont = NULL;
}

/* --Methode-- */
PILayoutMgr::~PILayoutMgr()
{
mPaSup = true;   // Pour prevenir ChildDel()
if (mACSup)
  for(int i=0; i<mNCh; i++)  delete mChilds[i];
delete[] mChilds;
}

/* --Methode-- */
void PILayoutMgr::ChildAdd(PIWdg* child)
{
if (child == NULL)  return;
if (mNCh == mMxCh)
  {
  PIWdg ** och = mChilds;
  mChilds = new (PIWdg * [mMxCh+NCHALGRP]);
  for(int i=0; i<mNCh; i++)  mChilds[i] = och[i];
  delete[] och;
  mMxCh += NCHALGRP;
  }  
mChilds[mNCh] = child;   mNCh++; 
return;
}

/* --Methode-- */
void PILayoutMgr::ChildDel(PIWdg* child)
{
if (mPaSup) return;  // Ne rien faire si delete initie par Container-parent : Le LayoutMgr lui-meme
if ((child == NULL) || (mNCh < 1))  return;
for(int i=0; i<mNCh; i++)  
  if (mChilds[i] == child)
    {
    mNCh--;
    mChilds[i] = mChilds[mNCh];
    break;
    }
return;
}

