//  Classe de base pour les objets correspondant a une fenetre 
//  dans les programmes graphiques interactives
//
//                  E.Aubourg , R. Ansari  96 - 98
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include <stdlib.h>
#include <stdio.h>

#include "piwdggen.h"
#include "picontainergen.h"
#include "pievthandler.h"
#include "psfile.h"

//++
// Class	PIWdg
// Lib		PI
// include	piwdggen.h
//
//   	Classe de base pour tout objets correspondant à une fenêtre
//	à l'écran, ayant donc une représentation graphique et 
//	pouvant jouer un rôle dans la hiérarchie des objets interactif. 
//	*PIWdg* hérite de *PIMsgHandler*, avec une hiérarchie correspondant
//	par défaut à celles des PIWdg. La classe "PIWdg" est une des 
//	classes de PI qui ont une implementation dépendante du systeme utilisé
//	(Mac, XWindow, ...). La classe "PIWdgGen" est la classe qui
//	définit l'interface, et ne doit pas être instanciée directement
//	(Méthodes virtuelles pures). Les objets instanciés sont de la 
//	classes "PIWdg" et le fichier entête correspondant est "PIWDG_H"
//	défini dans "pisysdep.h"
//--
//++
// Links	Parents
// PIMsgHandler
//--
//++
// Links	Voir aussi
// PIEventHandler
//--

//++
// Titre	Constructeur
//--
//++
// PIWdg(PIContainerGen *par, const char *nom, int sx=10, int sy=10, int px=0, int py=0)
//	Création d'un objet contenu dans l'objet *PIContainer* "par", de
//	taille "sx,sy", se trouvant à la position "px,py" avec le nom "nom"
// long kind()
//	Renvoie le type de la classe de l'objet ("=PIWdgGen::ClassId") pour cette classe
//	de base. Doit être redéfinie par les classes dérivées.
//--  


//++
// Titre	Taille, position
//--
//++
// void  PSPrint(PSFile *psf, int ofx=0, int ofy=0)
//	Méthode virtuelle qui doit être redéfinie pour chacune des classes filles.
//	produit une représentation graphique de l'objet en Postscript.
// SetSize(int sx, int sy)
//	Modifie la taille de l'objet.
// SetPos(int px, int py)
//	Modifie la position de l'objet.
// int  XSize()  YSize()
//	Renvoient la taille (X,Y) de l'objet.
// int  XPos()  YPos()
//	Renvoient la position (X,Y) de l'objet.
// void  GetScreenPos(int & spx, int & spy)
//	Renvoie la position de l'objet sur l'écran.
//--
//++
// Titre	Couleurs, etc ...
//--
//++
// void  SetBackgroundColor(PIColors col=PI_White)
//	Choix de la couleur de fond.
// void  SetForegroundColor(PIColors col=PI_Black)
//	Choix de la couleur d'avant plan.
// PIColors  GetBackgroundColor()
//	Renvoie la couleur de fond
// PIColors  GetForegroundColor()
//	Renvoie la couleur d'avant-plan.
// void  EraseWindow(int x0=0, int y0=0, int dx=0, int dy=0) 
//	Efface la zone rectangulaire définie par le coin "(x0,y0)" ,
//	de taille "dx,dy" à l'aide de la couleur de fond.
//--

//++
// Titre	Gestion des accrochages (Binding)
//--
//++
// void  SetBinding(PIBindingKind left, PIBindingKind top, PIBindingKind right, PIBindingKind bottom)
//	Permet de contrôler le comportement de l'objet en cas de changement de taille 
//	du conteneur parent. La position de chaque bord peut être sans contrainte ("PIBK_free")
//	attachée à une distance fixe par rapport au bord opposé du conteneur ("PIBK_fixed"), 
//	ou à une position proportionnelle à la taille du conteneur parent. ("PIBK_elastic") 
// bool  GetBinding((PIBindingKind& left, PIBindingKind& top, PIBindingKind& right, PIBindingKind& bottom)
//	Permet de connaitre l'état des accrochages. Retourne "true" si les accrochages ont été
//	verrouillé (appel à "LockBinding()"), "false" sinon.
// void  LockBinding()
//	Verrouille l'état des accrochages. Appel à "SetBinding()" sera alors sans effet.
//	Permet à certains *LayouMgr* d'imposer une contrôle strict.
// void  UnLockBinding()
//	Deverrouille les accrochages.
//--

//++
// Titre	Etat de l'objet
//	L'objet peut se trouver dans l'état actif ou inactif. Cet état est contrôlé par les 
//	méthodes "Manage(), UnManage()". L'objet ne se trouve effectivement dans l'état 
//	actif que si son conteneur parent est lui même actif.
//	L'objet peut aussi être affichés, mais insensible aux actions utilisateur
//	(clavier, souris, ...). Cette sensibilité est controlée par les 
//	méthodes  "SetSensitive(), SetUnSensitive()".
//--
//++
// void  Manage()  UnManage()
//	Change l'état de l'objet (actif, inactif)
// bool  IfManaged()  IfVisible()
//	indique si l'objet est actif , visible	
// void  SetSensitive() SetUnSensitive()
//	Rend l'objet sensible/ insensible aux actions utilisateurs (clavier, souris, ...)
//	L'état visuel de l'objet peut être modifié en conséquence.
// bool  IfSensitive() 
//	indique si l'objet est répond aux sollicitations utilisateur.
//--

//++
// Titre	Rafraîchissement de la fenêtre
//--
//++
// void  Refresh()
//	L'appel à cette méthode permet de retracer le contenu de la 
//	fenêtre et des "Drawer" associés.
//--

//++
// Titre	Méthodes
//--

//++
// void SetMsg(PIMessage msg = 0)
//	Modifie la valeur du message associé à l'objet.
// PIMessage  Msg()
//	Renvoie le message associé à l'objet.
// string  Nom()
//	Renvoie le nom associé à l'objet.
// PIWdg*  Parent()
//	Renvoie le conteneur parent de l'objet.
// void  SetUserData( void * p, int fg = 0)
//	Associe un pointeur de données à la disposition de l'utilisateur 
//	("void* p") à l'objet, ainsi qu'une valeur ("int fg")
// void* UserData()
//	Renvoie le pointeur de données user de l'objet. (NULL par défaut)
// int  UserFlag()
//	Renvoie la valeur "int" user de l'objet.
//--

//++
// Titre	Gestion du copier/coller
//	L'ensemble des méthodes de gestion de copier/coller sont décrites ici. Les méthodes
//	"SelectionLost()", "ProvideSelection()", et "PasteSelection()" doivent être 
//	redéfinies par les classes héritières de *PIWdg* implémentant la fonctionalité
//	copier/coller. Le mécanisme copier/coller entre objets d'une même application,
//	ainsi qu'entre différentes applications. Dans les opérations de copier/coller,
//	il existe un PIWdg ou une application source des données et un PIWdg ou 
//	une application destinatire.
//--

//++
// bool  ClaimSelection(int typ=PICP_string)
//	Cette méthode doit être appelée par l'objet "PIWdg" source quand celui-ci veut 
//	s'approprier la zone d'échange de données (Selection) pour le copier/coller. "typ" indique 
//	le type de données que peut fournir l'objet. Le type "PICP_string" (suite de caractères)
//	est le seul type supporté actuellement. La valeur de retour est "true" si 
//	la zone d'échange est attribué a l'objet. Cette méthode ne doit en principe pas 
//	être redéfinie par les classes héritières de *PIWdg*.
// void  SelectionLost()
//	Cette méthode est appelée quand l'objet "PIWdg" source qui possede la zone d'échange 
//	(Selection) perd celle-ci, suite par exemple à la demande d'un autre objet. Cette méthode 
//	doit être redéfinies par les classes qui implémentent la fonctionalité et ne doit 
//	doit pas être appelée directement.
// int  RequestSelection(int typ=PICP_string)
//	Cette méthode doit être appelée par l'objet "PIWdg" destinatire quand celui-ci souhaite 
//	obtenir les données de la zone d'échange (Selection). "typ" indique les types de données 
//	acceptables par l'objet. La valeur de retour indique le type qui sera fourni
//	(à l'appel de "PasteSelection()"). Cette méthode ne doit en principe pas 
//	être redéfinie par les classes héritières de *PIWdg*.
// void* ProvideSelection(int& typ, int& len)  
//	Cette méthode est appelée quand l'objet "PIWdg" source, qui possede la zone d'échange 
//	(Selection) doit  fournir les données correspondantes à la sélection. Renvoie le pointeur 
//	de la zone mémoire correspondante, sa longueur ("len") et le type ("typ") des données.
//	cette zone mémoire appartient à l'objet, et ne doit être modifié tant que 
//	la méthode "SelectionTransferEnd()" n'a été appelé.
// void  SelectionTransferEnd()
//	Cette méthode est appelé une fois que l'objet ou l'application destinataire 
//	des données de sélection a fini de traiter l'opération de copie. l'objet PIWdg 
//	source peut alors détruire ou modifier les données correspondantes à l'échange.
// void  PasteSelection(int typ, void *pdata, int l)
//	Cette méthode est appelée après l'appel à "RequestSelection()" pour l'objet 
//	destinataire. "typ" indique le type des données dans "pdata", et "l" la longeur. 
//	La zone mémoire "pdata" n'appartient pas à l'objet destinataire et ne doit pas 
//	être modifié par celui-ci. Une copie doit être effectué si cesCette méthode  données devaient
//	être utilisées après la sortie de "PasteSelection()".
//--

/* --Methode-- */
PIWdgGen::PIWdgGen(PIContainerGen *par, const char*, int, int, int, int)
: PIMsgHandler(par)
{
parent = par;
bindingLock = false;
SetMsg(0);
SetUserData(NULL, 0);
//  ChildAdd() doit etre appele par la classe qui implemente le widget
// if (par)  par->ChildAdd(this);   //  On previent le container parent  
return;
}


/* --Methode-- */
PIWdgGen::~PIWdgGen()
{
//  ChildDel() doit etre appele par la classe qui implemente le widget
// if (parent)  parent->ChildDel(this);   //  On previent le container parent 
list<EvHand>::iterator it;
for(it= mDHlist.begin(); it != mDHlist.end(); it++) 
  if ((*it).ad) delete (*it).evh;
for(it= mEHlist.begin(); it != mEHlist.end(); it++) 
  if ((*it).ad) delete (*it).evh;
}

/* --Methode-- */
void PIWdgGen::SetMsg(PIMessage msg)
{
myMsg = msg;
}

/* --Methode-- */
void PIWdgGen::GetScreenPos(int & spx, int & spy)
/*  Renvoie la position de la fenetre par rapport a l'ecran */
{
PIWdgGen * wc;
spx = 0;  spy = 0;
wc = this;

while (wc) 
  { spx += wc->XPos();  
  spy += wc->YPos();  wc = wc->Parent();
  }
return;
}

/* --Methode-- */
void PIWdgGen::LockBinding()
{
bindingLock = true;
}

/* --Methode-- */
void PIWdgGen::UnLockBinding()
{
bindingLock = false;
}

/* --Methode-- */
void PIWdgGen::PSPrint(PSFile *psf, int ofx, int ofy, double scale_x, double scale_y)
{
char str[256];

if (!psf) return;
double dx = (double)XSize()*scale_x;
double dy = (double)YSize()*scale_y;
psf->NewBloc((double)ofx+XPos(), (double)ofy+YPos(), dx, dy, dx, dy);
psf->DrawBox(0., 0., dx, dy);
sprintf(str,"PIWdgGen::PSPrint() Kind=%ld Name= %s", kind(), Nom().c_str());
// N.R. 07/08/99 FontName specifie dans DrawString() 
psf->DrawString(12., 12., str, PI_Black, PI_DefaultFont, PI_RomanFont, 10);
psf->EndBloc();

return;
}

//++
// Titre	Gestion des Draw/Event Handler
//	Les objets de la classe "PIWdg" peuvent gérer des objets "PIEventHandler" 
//	qui peuvent prendre en charge une partie du traitement des événements
//	clavier-souris-écran.
//--

//++
// void AddDrawHandler(PIEventHandler* drwh, bool ad=false)
//	Ajout d'un objet gestionnaire d'événements, responsable du tracé du contenu de la fenêtre.
//	La méthode "Draw(PIGraphic* g, ...)" sera appelé pour rafraîchir le contenu de la fenêtre.
// void RemoveDrawHandler(PIEventHandler* drwh)
//	Suppression d'un objet gestionnaire de tracé. Toutes les réferences sonnt supprimées en cas 
//	d' enregistrement multiple.
// void AddEventHandler(PIEventHandler* evh, unsigned long evtmask, bool ad=false)
//	Ajout d'un objet gestionnaire d'événements. La variable "evtmask" détermine pour
//	quels types d'événements, la méthode "Process()" du gestionnaire est appelée.
//|	PIEvent_Resize   (Non implementé en version X11 , 12/98)
//|	PIEvent_Enter , PIEvent_Leave
//|	PIEvent_ButxPress, PIEvent_ButxRelease (x=1,2,3)
//|	PIEvent_PtrMove , PIEvent_PtrxMove (x=1,2,3)
//|	PIEvent_Keyboard
//
// void RemoveEventHandler(PIEventHandler* evh)
//	Suppression d'un gestionnaire d'événements. Toutes les réferences sonnt supprimées en cas
//	d' enregistrement multiple, même avec différents masques d'événements.
//--

/* --Methode-- */
void PIWdgGen::AddDrawHandler(PIEventHandler* drwh, bool ad)
{
EvHand eh;
eh.evh = drwh; eh.mask = PIEvent_Draw;  eh.ad = ad;
mDHlist.push_back(eh);
}

/* --Methode-- */
void PIWdgGen::RemoveDrawHandler(PIEventHandler* drwh)
{
list<EvHand>::iterator it;
bool found = true;
while (found) {
  found = false;
  for(it= mDHlist.begin(); it != mDHlist.end(); it++) 
    if ((*it).evh == drwh) { mDHlist.erase(it); found = true; break; }
  }
}

/* --Methode-- */
void PIWdgGen::AddEventHandler(PIEventHandler* evh, unsigned long evtmask, bool ad)
{
EvHand eh;
eh.evh = evh; eh.mask = evtmask;  eh.ad = ad;
mEHlist.push_back(eh);
}

/* --Methode-- */
void PIWdgGen::RemoveEventHandler(PIEventHandler* evh)
{
list<EvHand>::iterator it;
bool found = true;
while (found) {
  found = false;
  for(it= mEHlist.begin(); it != mEHlist.end(); it++) 
    if ((*it).evh == evh) { mEHlist.erase(it); found = true; break; }
  }
}


/* --Methode-- 
string PIWdgGen::kindstr()
{
char b[5];
string s;

b[0] = (char) (kind()&0x000000FF);
b[1] = (char) ((kind()&0x0000FF00) / 0x100);
b[2] = (char) ((kind()&0x00FF0000) / 0x10000);
b[3] = (char) ((kind()&0xFF000000) / 0x1000000);
b[4] = '\0';
s = b;
return(s);
}
*/

//++
// Class	PIScreenBuffer
// Lib		PI
// include	piwdggen.h
//
//	Classe de tampon de dessin hors écran. Permet la copie du contenu des pixels
//	depuis et vers des objets "PIWdg", ainsi que depuis et vers d'autres tampon
//	d'écran. Un objet "PIGraphic" peut-être instancié pour fournir les services
//	de dessin dans un "PIScreenBuffer"
//--
//++
// Links	Voir aussi
// PIWdg
// PIGraphic
//--

//++
// Titre	Constructeurs, méthodes
//--
//++
// PIScreenBuffer(int sx, int sy)
//	Constructeur, création d'un tampon de taille "sx * sy" pixels.
// int  XSize()
//	Renvoie la taille en X.
// int  YSize()
//	Renvoie la taille en Y.
//
//	Pour les opérations de copie, le rectangle source est défini par
//	la position du coin haut-gauche "(ox,oy)" et la taille "dx * dy" en pixels.
//	La copie s'effectue sur l'objet destination à partir de l'offset "(x,y)".
//
// void CopyFromWdg(PIWdg* wdg, int ox, int oy, int dx, int dy, int x, int y)
//	Copie depuis l'objet "PIWdg* wdg".
// void CopyToWdg(PIWdg* wdg, int ox, int oy, int dx, int dy, int x, int y)
//	Copie vers l'objet "PIWdg* wdg".
// void CopyFrom(PIScreenBuffer* grb, int ox, int oy, int dx, int dy, int x, int y)
//	Copie depuis l'objet "PIScreenBuffer* grb"
//--
