#ifndef __OTreeList__H
#define __OTreeList__H

#include <stdint.h>

#include "WimpLib:Template.h"
#include "WimpLib:WListCore.h"

#define EWOTreeItemArea_ExpandOrCollapse     (EWItemArea_User + 0)
#define EWOTreeItemArea_ExplodeOrCollapse    (EWItemArea_User + 1)
#define EWOTreeItemArea_ExplodeAllOrCollapse (EWItemArea_User + 2)
#define EWOTreeItemArea_User                 (EWItemArea_User + 3)

typedef struct OTreeNode OTreeNode;
typedef struct OTreeList OTreeList;
typedef struct OTreeNodeVPtr OTreeNodeVPtr;

typedef void (*throw_OTreeNode_FAllocData)(OTreeNode*, void* pData, const void* pRefData);
typedef void (*OTreeNode_FClearData)(OTreeNode*, void* pData);
typedef void (*OTreeNode_FOnExpand)(const OTreeNode*);
typedef int  (*OTreeNode_FCompare)(const void* pData, const void* pNodeData);

struct OTreeNodeVPtr
{
	// display
	WItem_VTable                     item;
	// data management
	throw_OTreeNode_FAllocData       throw_FAllocData;
	OTreeNode_FClearData             FClearData;
	// childs management
	OTreeNode_FOnExpand              FOnExpand;
	OTreeNode_FCompare               FCompare;
};

OTreeNode* throw_New_OTreeNode(const OTreeNodeVPtr* pNodeVPtr, uint32_t size, const void* pData);
OTreeNode* throw_OTreeNode_InsertChild(OTreeNode* This, const OTreeNodeVPtr* pNodeVPtr, uint32_t size, const void* pData);

void Delete_OTreeNode(OTreeNode*);
const OTreeNodeVPtr* OTreeNode_GetVPtr(const OTreeNode*);
const void* OTreeNode_GetData(const OTreeNode*);
int OTreeNode_CountChilds(const OTreeNode*);
OTreeNode* OTreeNode_GetParent(const OTreeNode*);
OTreeNode* OTreeNode_GetFirstChild(const OTreeNode*);
OTreeNode* OTreeNode_GetPredecessor(const OTreeNode*);
OTreeNode* OTreeNode_GetSuccessor(const OTreeNode*);
int OTreeNode_GetLevel(const OTreeNode*);

OTreeList* OTreeNode_GetTreeList(const OTreeNode*);
void OTreeNode_SetTreeList(OTreeNode* pNode, OTreeList* pTreeList);

bool OTreeNode_AllowExpand(const OTreeNode*);
bool OTreeNode_IsExpanded(const OTreeNode*);
void OTreeNode_SetExpanded(OTreeNode* This, bool bExpanded);

int OTreeNode_DefWidth(const OTreeNode*);
void OTreeNode_DefArea(const OTreeNode*, const WPlotItem* pItem, const Mouse* pMouse, WItemArea* pArea);
void OTreeNode_PlotGrid(const OTreeNode*, const WPlotItem* pItem);


OTreeList* throw_New_OTreeList(unsigned int flags, CTemplate* t, OTreeNode* pRootNode, void* pHandle, int NrDrawSizes);
void Delete_OTreeList(OTreeList*);

HWind OTreeList_GetWindow(const OTreeList*);
WListCore* OTreeList_GetWListCore(OTreeList*);
int OTreeList_ExpandParents(OTreeList*, const OTreeNode* pNode);
void OTreeList_ShowItem(OTreeList*, int index);
int OTreeList_Expand(OTreeList* This, int index, int mode, bool bShow);

OTreeNode* OTreeList_GetWListItem(const OTreeList*, int index);
OTreeNode* OTreeList_GetRootNode(const OTreeList*);
void OTreeList_SetRootNode(OTreeList*, OTreeNode* pRootNode);
void OTreeList_Update(OTreeList*, OTreeNode* pNode);
void OTreeList_Remove(OTreeList*, OTreeNode* pNode);

void OTreeList_AllowRefresh(OTreeList*, bool bAllow);
#define OTreeList_IsRefreshAllowed(This) WListCore_IsRefreshAllowed(OTreeList_GetWListCore(This))
#define OTreeList_Refresh(This, ...) WListCore_Refresh(OTreeList_GetWListCore(This), __VA_ARGS__)
#define OTreeList_SetParent(This, ...) WListCore_SetParent(OTreeList_GetWListCore(This), __VA_ARGS__)
#define throw_OTreeList_SetPane(This, ...) throw_WListCore_SetPane(OTreeList_GetWListCore(This), __VA_ARGS__)
#define OTreeList_SetExtent(This) WListCore_SetExtent(OTreeList_GetWListCore(This))

#endif
