#ifndef _CUSTOMGUI_TREEVIEW_H_
#define _CUSTOMGUI_TREEVIEW_H_

#include "customgui_base.h"
#include "c4d_basecontainer.h"



#define CUSTOMGUI_TREEVIEW		1000475 // user gadget


#define TREEVIEW_BORDER             'brdr'
#define TREEVIEW_OUTSIDE_DROP       'tvod' // TRUE, if object may be dropped under all objects in the tree view
#define TREEVIEW_HIDE_LINES         'tvhl' // TRUE, if no lines should be drawn
#define TREEVIEW_CTRL_DRAG          'ctdr' // TRUE, if item may be duplicated by Ctrl + Drag
#define TREEVIEW_NO_MULTISELECT     'tvnm' // TRUE, if no multi select is allowed
#define TREEVIEW_HAS_HEADER         'tvhh' // TRUE, if the tree view may have a header line
#define TREEVIEW_RESIZE_HEADER      'tvrh' // TRUE, if the column width can be changed by the user
#define TREEVIEW_MOVE_COLUMN        'tvmc' // TRUE, if the user can move a column


#define LV_TREE 'tree'
#define LV_USER 'user'

typedef UCHAR OBSOLETE;

class GeUserArea;

struct CellInfo
{
	GeUserArea *frame;

	LONG xpos,ypos,width,height;
	LONG line,col;
};

struct DrawInfo : public CellInfo
{
};

struct MouseInfo : public CellInfo
{
	Real mx;
	Real my;
	BaseContainer msg;
	Bool rightButton;
};

struct DragInfo : public CellInfo
{
	Real	mx;
	Real	my;
	BaseContainer msg;

	void	*dragobject;
	LONG	dragtype;
};

// if bCont is false, the branch is not visited any more
typedef Bool (*VisitChildrenCallback)(void* root, void* obj, void* userdata, void* data1, void* data2, Bool &bCont);

enum
{
  ID_TREEVIEW_CONTEXT_REMOVE = FIRST_POPUP_ID,
  ID_TREEVIEW_CONTEXT_RESET,
  ID_TREEVIEW_FIRST_NEW_ID = FIRST_POPUP_ID + 10
};

class TreeViewFunctions
{
	public:
		// Navigation Functions
		virtual void*		GetFirst(void *root,void *userdata) = NULL;
		virtual void*		GetDown(void *root,void *userdata,void *obj) = NULL;
		virtual void*		GetNext(void *root,void *userdata,void *obj) = NULL;
		virtual void*		GetPred(void *root,void *userdata,void *obj); // only for drag&drop check

		// Layout functions
		virtual LONG		GetColumnWidth(void *root,void *userdata,void *obj,LONG col);
    virtual LONG		GetHeaderColumnWidth(void *root,void *userdata,LONG col); // return a negative number for auto header width
		virtual LONG		GetLineHeight(void *root,void *userdata,void *obj,LONG col);
		virtual void		DrawCell(void *root,void *userdata,void *obj,LONG col,DrawInfo *drawinfo, LONG bgColor);
    virtual Bool    DrawHeaderCell(void *root, void *userdata, LONG col, DrawInfo *drawinfo); // return FALSE if the header should be drawn by the tree view

		// Get Functions
		virtual Bool		IsSelected(void *root,void *userdata,void *obj) = NULL;
		virtual Bool		IsOpened(void *root,void *userdata,void *obj) = NULL;
		virtual String	GetName(void *root,void *userdata,void *obj) = NULL;
    virtual LONG		GetId(void *root,void *userdata,void *obj) = NULL;
		virtual LONG		GetDragType(void *root,void *userdata,void *obj) = NULL; // return NOTOK to disable D&D
    virtual void    GetColors(void *root,void *userdata,void *obj, GeData* pNormal, GeData* pSelected);
    virtual LONG		GetMinHeaderHeight(void *root,void *userdata); // return < 0 for auto header height

    // Note : CreateContextMenu and ContextMenu were replaced by CreateContextMenuColumn and ContextMenuColumn with version 8.15
    virtual OBSOLETE CreateContextMenu(void *root, void *userdata, void *obj, BaseContainer* bc);
    virtual OBSOLETE ContextMenu(void *root,void *userdata,void *obj, LONG lCommand); // called by a command in the context menu, return TRUE if you processed the message

    // bc already contains a delete elment, you may delete the contents of bc. Your own elements should start at ID_TREEVIEW_FIRST_NEW_ID
    virtual void    CreateContextMenuColumn(void *root, void *userdata, void *obj, LONG lColumn, BaseContainer* bc);
    // return TRUE, if you proceeded the command and the data needs to be updated
    virtual Bool    ContextMenuColumn(void *root,void *userdata,void *obj, LONG lColumn, LONG lCommand); // called by a command in the context menu, return TRUE if you processed the message

    virtual Bool    IsTristate(void *root, void *userdata);

		// Set Functions
		virtual void		Open(void *root,void *userdata,void *obj,Bool onoff);
		virtual void		Select(void *root,void *userdata,void *obj,LONG mode);
		virtual LONG		AcceptDragObject(void *root,void *userdata,void *obj,LONG dragtype,void *dragobject, Bool &bAllowCopy); // retrun INSERT_xxx
    // if obj == NULL, the dragobject sould be inserted as a child of the root 
    virtual void		InsertObject(void *root,void *userdata,void *obj,LONG dragtype,void *dragobject,LONG insertmode, Bool bCopy);
			#define INSERT_BEFORE		(1<<0)
			#define INSERT_AFTER		(1<<1)
			#define INSERT_UNDER		(1<<2)

    virtual void    SetName(void *root,void *userdata,void *obj, const String &str);
    virtual void    SetDragObject(void *root,void *userdata,void *obj);
    virtual void    GenerateDragArray(void *root,void *userdata,void *obj, AtomArray* ar);

		virtual Bool		MouseDown(void *root,void *userdata,void *obj,LONG col,MouseInfo *mouseinfo, Bool rightButton);
    virtual Bool		DoubleClick(void *root,void *userdata,void *obj,LONG col,MouseInfo *mouseinfo); // return FALSE, if you want to open the rename dialog
    virtual void    DeletePressed(void *root, void *userdata);

    virtual void    SelectionChanged(void *root, void *userdata);
    virtual LONG    GetHeaderSortArrow(void *root, void *userdata, LONG lColID);
    virtual Bool    HeaderClick(void *root, void *userdata, LONG lColID, LONG lChannel, Bool bDblClk); // return TRUE, if the tree view needs to be updated
    virtual Bool    UserCanResizeCol(void *root, void *userdata, LONG lColID);
    virtual Bool    UserCanMoveCol(void *root, void *userdata, LONG lColID);

    // called after the user released the cursor, return FALSE if you want to cancel the layout change
    // NOTE : lInsertBeforeCol is the index of the column
    virtual Bool    ColumnMoved(void *root, void *userdata, LONG lColID, LONG lInsertBeforeCol, LONG* plIndexMap);

    // non-overridable

    // calls fn for obj and all its children
    Bool VisitChildren(void* root, void* obj, VisitChildrenCallback fn, void* userdata, void* data1, void* data2);
};


// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
class TreeViewCustomGui;

class TreeViewF
{
public:
    // version 8.0
		void*  GetFirst(TreeViewFunctions* pFuncs, void *root,void *userdata);
		void*  GetDown(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
		void*  GetNext(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
		void*  GetPred(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
		LONG   GetColumnWidth(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col);
		LONG   GetLineHeight(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col);
		void   DrawCell(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col,DrawInfo *drawinfo, LONG bgColor);
    Bool   DrawHeaderCell(TreeViewFunctions* pFuncs, void *root,void *userdata,LONG col,DrawInfo *drawinfo);
		Bool   IsSelected(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
		Bool   IsOpened(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
		String GetName(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
    LONG   GetId(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
		LONG   GetDragType(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
    void   GetColors(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, GeData* pNormal, GeData* pSelected);
    void   CreateContextMenu(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, BaseContainer* bc); // only for compatibility
    Bool   ContextMenu(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, LONG lCommand); // only for compatibility
    Bool   IsTristate(TreeViewFunctions* pFuncs, void *root, void *userdata);
		void   Open(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,Bool onoff);
		void   Select(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG mode);
		LONG   AcceptDragObject(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG dragtype,void *dragobject, Bool &bAllowCopy);
    void   InsertObject(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG dragtype,void *dragobject,LONG insertmode, Bool bCopy);
    void   SetName(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, const String &str);
    void   SetDragObject(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
    void   GenerateDragArray(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, AtomArray* ar);
		Bool   MouseDown(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col,MouseInfo *mouseinfo, Bool rightButton);
    Bool   DoubleClick(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col,MouseInfo *mouseinfo);
    void   DeletePressed(TreeViewFunctions* pFuncs, void *root, void *userdata);

    // version 8.1
    void    SelectionChanged(TreeViewFunctions* pFuncs, void *root, void *userdata);
    LONG    GetHeaderSortArrow(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID);
    Bool    HeaderClick(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID, LONG lChannel, Bool bDbl);
    Bool    UserCanResizeCol(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID);
    Bool    UserCanMoveCol(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID);
    Bool    ColumnMoved(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID, LONG lInsertBeforeCol, LONG* plIndexMap);
    LONG		GetHeaderColumnWidth(TreeViewFunctions* pFuncs, void *root,void *userdata,LONG col);
    LONG		GetMinHeaderHeight(TreeViewFunctions* pFuncs, void *root,void *userdata);

    // new from version 8.15
    void   CreateContextMenuColumn(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, LONG lColumn, BaseContainer* bc);
    Bool   ContextMenuColumn(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, LONG lColumn, LONG lCommand);
};

struct InternalFunctionTable
{
  // tree view version 8.0
  void*		(TreeViewF::*GetFirst)(TreeViewFunctions* pFuncs, void *root,void *userdata);
	void*		(TreeViewF::*GetDown)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
	void*		(TreeViewF::*GetNext)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
	void*		(TreeViewF::*GetPred)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj); // only for drag&drop check

	// Layout functions
	LONG		(TreeViewF::*GetColumnWidth)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col);
	LONG		(TreeViewF::*GetLineHeight)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col);
	void		(TreeViewF::*DrawCell)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col,DrawInfo *drawinfo, LONG bgColor);

	// Get Functions
	Bool		(TreeViewF::*IsSelected)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
	Bool		(TreeViewF::*IsOpened)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
	String	(TreeViewF::*GetName)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
  LONG		(TreeViewF::*GetId)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
	LONG		(TreeViewF::*GetDragType)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj); // return NOTOK to disable D&D
  void    (TreeViewF::*GetColors)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, GeData* pNormal, GeData* pSelected);
  // bc already contains a delete elment, you may delete the contents of bc. Your own elements should start at ID_TREEVIEW_FIRST_NEW_ID
  void    (TreeViewF::*CreateContextMenu)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, BaseContainer* bc);
  // return TRUE, if you proceeded the command and the data needs to be updated
  Bool    (TreeViewF::*ContextMenu)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, LONG lCommand); // calles by the delete command in the context menu
  Bool    (TreeViewF::*IsTristate)(TreeViewFunctions* pFuncs, void *root, void *userdata);

	// Set Functions
	void		(TreeViewF::*Open)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,Bool onoff);
	void		(TreeViewF::*Select)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG mode);
	LONG		(TreeViewF::*AcceptDragObject)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG dragtype,void *dragobject, Bool &bAllowCopy); // retrun INSERT_xxx
  // if obj == NULL, the dragobject sould be inserted as a child of the root 
  void		(TreeViewF::*InsertObject)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG dragtype,void *dragobject,LONG insertmode, Bool bCopy);
  void    (TreeViewF::*SetName)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, const String &str);
  void    (TreeViewF::*SetDragObject)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj);
  void    (TreeViewF::*GenerateDragArray)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, AtomArray* ar);

	Bool		(TreeViewF::*MouseDown)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col,MouseInfo *mouseinfo, Bool rightButton);
  Bool		(TreeViewF::*DoubleClick)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj,LONG col,MouseInfo *mouseinfo); // return FALSE, if you want to open the rename dialog
  void    (TreeViewF::*DeletePressed)(TreeViewFunctions* pFuncs, void *root, void *userdata);

  // version 8.1 functions
  void    (TreeViewF::*SelectionChanged)(TreeViewFunctions* pFuncs, void *root, void *userdata);
  LONG    (TreeViewF::*GetHeaderSortArrow)(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID);
  Bool    (TreeViewF::*HeaderClick)(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID, LONG lChannel, Bool bDbl);
  Bool    (TreeViewF::*UserCanResizeCol)(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID);
  Bool    (TreeViewF::*UserCanMoveCol)(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID);
  Bool    (TreeViewF::*ColumnMoved)(TreeViewFunctions* pFuncs, void *root, void *userdata, LONG lColID, LONG lInsertBeforeCol, LONG* plIndexMap);
	LONG		(TreeViewF::*GetHeaderColumnWidth)(TreeViewFunctions* pFuncs, void *root,void *userdata,LONG col);
	Bool		(TreeViewF::*DrawHeaderCell)(TreeViewFunctions* pFuncs, void *root,void *userdata,LONG col,DrawInfo *drawinfo);
  LONG		(TreeViewF::*GetMinHeaderHeight)(TreeViewFunctions* pFuncs, void *root,void *userdata);

  // version 8.15 functions
  void    (TreeViewF::*CreateContextMenuColumn)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, LONG lColumn, BaseContainer* bc);
  Bool    (TreeViewF::*ContextMenuColumn)(TreeViewFunctions* pFuncs, void *root,void *userdata,void *obj, LONG lColumn, LONG lCommand); // calles by the delete command in the context menu

  void* dummy[(50 - 37) * C4DPL_MEMBERMULTIPLIER];
};




// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF


class TreeViewCustomGui : public BaseCustomGui<CUSTOMGUI_TREEVIEW>
{
		TreeViewCustomGui();

	public:
    Bool    SetRoot(void *root,TreeViewFunctions *functions,void *userdata);
		Bool		SetLayout(LONG columns,const BaseContainer &data);
    Bool    SetHeaderText(LONG lColumnID, const String &str);
    GeUserArea* GetTreeViewArea();
    GeUserArea* GetHeaderArea();
		void		Refresh();
    LONG    GetAutoColumnWidth(LONG lColID); // the auto-width of the column
    LONG    GetColumnWidthUser(LONG lColID); // the size the user has set
    LONG    GetRealColumnWidth(LONG lColID); // the real column width
    Bool    SetColumnWidthUser(LONG lColID, LONG lWidth);
};



// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF


#ifndef _INTERNAL_DEF_
	class iTreeViewCustomGui
	{
	};
#else
	class iTreeViewCustomGui;
#endif

struct TreeViewLib : public BaseCustomGuiLib
{
	Bool    (iTreeViewCustomGui::*SetRoot		)(void *root, InternalFunctionTable* f, void *userdata, LONG lSize, TreeViewF* pControl, TreeViewFunctions* pFunctions);
	void		(iTreeViewCustomGui::*Refresh		)();
	Bool		(iTreeViewCustomGui::*SetLayout	)(LONG columns,const BaseContainer &data);
  Bool		(iTreeViewCustomGui::*ShowObject)(void *o);
  Bool    (iTreeViewCustomGui::*SetHeaderText)(LONG lColumnID, const String &str);
  GeUserArea* (iTreeViewCustomGui::*GetTreeViewArea)();
  GeUserArea* (iTreeViewCustomGui::*GetHeaderArea)();
  LONG    (iTreeViewCustomGui::*GetAutoColumnWidth)(LONG lColID);
  LONG    (iTreeViewCustomGui::*GetColumnWidthUser)(LONG lColID);
  LONG    (iTreeViewCustomGui::*GetRealColumnWidth)(LONG lColID);
  Bool    (iTreeViewCustomGui::*SetColumnWidthUser)(LONG lColID, LONG lWidth);
};

// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF
// INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF -- INTERNAL STUFF

#endif
