#ifndef _COBJECTBASE_H_
#define _COBJECTBASE_H_

#include "../x/Version.h"
#include "../x/scolplugin.h"
#include "../x/Objstr.h"
#include "Rect.h"
#include "CObjBuffer.h"

#include "CObjLink.h"
#include "CObjToolTip.h"

#define DEBUG_OBJNODE 0

#define OBJ_ENABLE	  (1<<0)
#define OBJ_DISABLE	  (1<<1)
#define OBJ_VISIBLE	  (1<<2)
#define OBJ_HIDE	  (1<<3)
#define LAST_OBJ_VISI	3
#define OBJ_CBNOPAINT (1<<4)
#define OBJ_TABSTOP	  (1<<5)
#define LAST_OBJ_COM	5
#define OBJ_LW_FLEX	  (1<<6)
#define OBJ_MW_FLEX	  (1<<7)
#define OBJ_RW_FLEX	  (1<<8)
#define OBJ_LH_FLEX	  (1<<9)
#define OBJ_MH_FLEX	  (1<<10)
#define OBJ_RH_FLEX	  (1<<11)
#define LAST_OBJ_FLAG	11

#define NB_RFLOBJNODE				15
#define RFLOBJNODE_CURSORMOVE					0
#define RFLOBJNODE_CURSORMOVEIN				1
#define RFLOBJNODE_CURSORMOVEOUT			2
#define RFLOBJNODE_CLICK							3
#define RFLOBJNODE_UNCLICK						4
#define RFLOBJNODE_DBLCLICK						5
#define RFLOBJNODE_CHANGE							6
#define RFLOBJNODE_VALIDATION					7
#define RFLOBJNODE_TOOLTIP_ON					8
#define RFLOBJNODE_TOOLTIP_OFF				9
#define RFLOBJNODE_RESIZE_RESSOURCE		10
#define RFLOBJNODE_RESIZE							11
#define RFLOBJNODE_SCLICK							12
//$BLG - v5.01: Add
#define RFLOBJNODE_KEYDOWN						13
#define RFLOBJNODE_KEYUP							14

#define NO_TRANSPARENCY -1

// flags de passage des evenements au container
#define OBJ_CONTAINER_CLICK      (1<<0)
#define OBJ_CONTAINER_UNCLICK    (1<<1)
#define OBJ_CONTAINER_DBLCLICK   (1<<2)
#define OBJ_CONTAINER_KEYUP	     (1<<3)
#define OBJ_CONTAINER_KEYDOWN    (1<<4)
#define OBJ_CONTAINER_MOUSEWHEEL (1<<5)
#define OBJ_CONTAINER_MOVE       (1<<6)
//$BLG - Note: This one doesn't seem to be implemented ...
#define OBJ_CONTAINER_RESIZE	 	 (1<<7)
//$BLG - v5.11: Add
//Activates all implemented events filter flags
#define OBJ_CONTAINER_ALLEVENTS  (OBJ_CONTAINER_CLICK|OBJ_CONTAINER_UNCLICK|OBJ_CONTAINER_DBLCLICK|OBJ_CONTAINER_KEYUP|OBJ_CONTAINER_KEYDOWN|OBJ_CONTAINER_MOUSEWHEEL|OBJ_CONTAINER_MOVE)

class container;


class CObjectBase:public CObjLink
{
	//////////////////////////////////////////////
	//  Variables
	//////////////////////////////////////////////

private:
	// le container auquel appartient l'objet
	container * ObjContainer;

	int ObjXi;		// coordonées initiales de l'objet
	int ObjYi;		// utilisées pour le resize
	int ObjWi;
	int ObjHi;

	int ObjContWi;  // taille initiale du container auquel
	int ObjContHi;	// correspondent les coord initiales de l'objet
	
	void		   EvalCoordsResize(int,int);	// fonction evaluant les nouvelles coordonées
												// et la taille d'un objet en fonction de la nouvelle
												// taille du container
	int	ObjResourceDest;

protected:
	Layer * ObjLayer;

	int ObjFlags;	// flags de l'objet

	int ObjContainerFlags; // flags de filtrage de passage des evenements vers le container

	// en protected ??
	int ObjTransparency; // couleur de transparence de l'objet

	// fonction qui remplace la resource graphique d'un objnode et detruit la
	// precedente si necessaire
	int ChangeResource(mmachine,int,int);
	
public:	
	
	int ObjX;		// coordonnées par rapport au container
	int ObjY;

	int ObjXfat;	// coordonnées par rapport à l'objet pere
	int ObjYfat;
	
	int ObjW;		// largeur de l'objet
	int ObjH;		// hauteur de l'objet

	
	// le tooltip associé à l'objet
	CObjToolTip * ObjToolTip;

	//////////////////////////////////////////////
	// Fonctions
	/////////////////////////////////////////////
	
	// constructeur-destructeur
	CObjectBase(container *,Layer *,int,int,int,int,int,int,int);
	virtual ~CObjectBase();
	
	inline int			IsObjectEnabled(){return (ObjFlags&OBJ_ENABLE);};
	inline int			IsObjectVisible(){return (ObjFlags&OBJ_VISIBLE);};
	inline int			IsObjectTabStop(){return (ObjFlags&OBJ_TABSTOP);};
	inline int			IsObjectRepaintBeforeCallback(){return !(ObjFlags&OBJ_CBNOPAINT);};
	inline int			TransmitToContainer(int event){return (ObjContainerFlags&event);};
	inline container *	Container(){return ObjContainer;};
	inline void			setFlags(int newflags){ObjFlags=newflags;};
	inline int			getFlags(){return ObjFlags;};

	virtual Rect2D		RectangleIncludingObject();					// renvoie le rectangle englobant d'un objet
	void				ChangeCommonFlags(int newflags,int repaint);// modifie les flags communs d'un objet
	void				SetFocus();									// rends l'objet en focus

	// reaffichage
	void				Redraw();					// redessine l'objet
	void				RedrawPart(Rect2D);			// redessine une partie de l'objet
	
	// le redimensionnement
	void				SetIniResizeCoords();		// fonction de mise à jour des coordonées
												// de resize
	int					ResizeCont(int,int,int);		// fonction de redimensionnement en fonction du container
	int					Resize(int,int,int);			// fonction de redimensionnement

	// les methodes virtuelles
	virtual int IsMouseOnObject(int,int,int)=0;
	virtual int CursorMove(int,int,int,int,int)=0;
	virtual int CursorMoveIn(int,int,int,int,int)=0;
	virtual int CursorMoveInWithBtnPushed(int,int,int,int,int)=0;
	virtual int CursorMoveOut(int,int,int,int,int)=0;
	virtual int CursorMoveOutWithBtnPushed(int,int,int,int,int)=0;
	virtual int CursorMoveOutsideWithBtnPushed(int,int,int,int,int)=0;
	virtual int ClickIn(int,int,int,int,int,int)=0;
	virtual int UnClickIn(int,int,int,int,int,int)=0;
	virtual int ClickOut(int,int,int,int,int,int)=0;
	virtual int UnClickOut(int,int,int,int,int,int)=0;
	virtual int DblClickIn(int,int,int,int,int,int)=0;
	virtual int MouseWheel(int,int,int,int,int,int)=0;
	virtual int KeyUp(UINT,int,UINT,int)=0;
	virtual int KeyDown(UINT,int,int,UINT,int)=0;
	virtual int SetFocus(int,int,int)=0;
	virtual int KillFocus(int,int)=0;

	virtual int Timer(int)=0;

	virtual Layer *GetLayer(mmachine m,int p_tab)=0;
	virtual Layer *GetLayerPart(mmachine m,Rect2D *area2redraw,int p_tab)=0;
	
	virtual int DestroyAllLayers()=0; 			// fonction de destruction de ts les layers
	virtual int ResizeLayer(int,int,int)=0;		// fonction de redim d'un objet
	virtual int CanBeActiveObject(){return 0;};

};

typedef CObjectBase * PtrObjectBase;

/*********************************************************************************/
/*                       Fonctions sur l'objet OBJNODE                           */
/*********************************************************************************/
// cree l' ObjNode Root a partir de l'ObjBase root
int CrRoot(mmachine m,CObjectBase * root,int ndxchannel);

// ajoute un node dont le handleur systeme est (int)obj au node father si ce dernier est
// non null sinon au root 
//int AddNode(mmachine m,CObjectBase *root,CObjectBase * father,CObjectBase * obj, int nbparam,...);
int AddNode(mmachine m,CObjectBase *root,CObjectBase * father,CObjectBase * obj, int nbparam);

// detruit un node
// p_obj est le pointeur vers l'OBJNODE à détruire
int DsNode(mmachine m,int p_obj);

// methode de destruction interne d'un node
int DsNode2(mmachine,int,int);

// applique la fonction func sur tous les nodes 
void ApplyOnTree(int,mmachine,int,int (*func)(mmachine,int,va_list),...);

// fonction redimensionnant un node en fonction de
// la nouvelle taille du container
int ComputeResize(mmachine,int,va_list);

// recupere le pere d'un OBJNODE
int GetFather(mmachine,int);
// recupere le frere d'un OBJNODE
int GetBrother(mmachine,int);
// recupere le fils d'un OBJNODE
int GetSon(mmachine,int);
// recupere la valeur d'un OBJNODE
CObjectBase *GetObjectBase(mmachine,int);
// recupere le typetab d'un OBJNODE
int GetTab(mmachine m,int p_obj);

// renvoie l'objnode dont le handler systeme est le second parametre
int FindObjNodeFromHdlSys(mmachine m,int hdlsys);

// renvoie l'OBJNODE se trouvant sous la souris
int Search_ObjNode_Under_Mouse(mmachine m,int p_objnode,int MouseCol,int MouseLgn);

// redessine les ObjNodes de l'arbre dans le buffer offscreen
void PaintObjNodes(mmachine m,PtrObjBuffer b,int node);

// redessine les ObjNodes de l'arbre se situant dans la zone à redessiner dans le buffer offscreen
void PaintPartObjNodes(mmachine m,PtrObjBuffer b,int node,Rect2D area2redraw);

void PaintToolTip(CObjectBase *o,PtrObjBuffer blit);

int  GetResizeFlags(int flags);

/////////////////////////////////////////////////////////////////
//   Fonctions Scol
/////////////////////////////////////////////////////////////////

// operations sur l'ObjNode
int _CHANGEobjNodeFlags(mmachine);
int _GETobjNodeFlags(mmachine);
int _CHANGEobjNodeCoordinates(mmachine);
int _GETobjNodePositionSizeInFatherRef(mmachine);
int _GETobjNodePositionSizeInContainerRef(mmachine);
int _PAINTobjNode(mmachine);
int _TOPobjNode(mmachine);
int _SIZEobjNode(mmachine);
int _SETobjNodeFocus(mmachine);
int _SETobjNodeTabStopOrder(mmachine);

#if DEBUG_OBJNODE
	// affiche l'arbre des ObjNode
	void PrintTree(mmachine m,int prof,int node);
#endif

#endif