#include <windows.h>
#include <commctrl.h>

class TreeListView;

typedef struct TreeListViewNodeInfo {
	HWND	*check;
} TreeListViewNodeInfo;

typedef struct TreeListViewData {
	int		id;
	int		col;
	int		type;
	union {
		bool	flag;
		int		perc;
		LPTSTR	str;
	}		data;
	TreeListViewNodeInfo	*info;
	unsigned	child : 1;
	unsigned	editable : 1;
} TreeListViewData;

enum TreeListViewNotifMessage {
	TLVN_EXPAND,
	TLVN_REDRAW
};

typedef struct TreeListViewNotif {
	TreeListViewNotifMessage	message;
	int		id;
	int		col;
} TreeListViewNotif;

typedef void(*TreeListViewDataFunc)(TreeListView*, TreeListViewData*, bool set);
typedef void(*TreeListViewNotifFunc)(TreeListView*, TreeListViewNotif*);


class TreeListView
{
public:
	TreeListView(RECT *r, HWND parent, int id,
				int n, LPTSTR *titles, short *widths, char *types);
	virtual ~TreeListView();

	void	SetDataFunc(TreeListViewDataFunc func) { dataFunc = func; }
	void	SetNotifFunc(TreeListViewNotifFunc func) { notifFunc = func; }

	void	Insert(int id, int next, int parent);
	void	Remove(int id);
	void	Set(int id);
	void	Collapse(int id);
	void	Expand(int id);

	int		FindItem(int id);
	int		GetID(int index);
	HWND	GetHWnd() { return hList; }

	int		SelectedItemStart();
	int		SelectedItemIterate();

	bool	StartEdit(int id, int col) { return StartEditItem(FindItem(id), col); }
	bool	StartEditItem(int index, int col);
	void	FinishEdit();
	void	EndEdit();

	void	CollapseItem(int index);
	void	ExpandItem(int index);
	void	DrawItems(LPDRAWITEMSTRUCT lpDraw);
	void	MoveCheckBox();

	void	SetUserData(void *data) { user_data = data; }
	void *	GetUserData() { return user_data; }

	void	SetColumnWidth(int col, short w);
	short	GetColumnWidth(int col);

	void	SetAutoACWMode(bool flag) { acw_mode = flag; if (flag) AdjustColumnWidth(); }
	bool	GetAutoACWMode()	{ return acw_mode; }
	bool	AdjustColumnWidth(int col=-1, HDITEM *item=NULL);

protected:
	static int  CALLBACK ListViewProc(HWND hWnd, unsigned wMessage, WPARAM wParam, LPARAM lParam);
	static int  CALLBACK EditProc(HWND hWnd, unsigned wMessage, WPARAM wParam, LPARAM lParam);
	static void CALLBACK EditTimerProc(HWND hwnd, UINT msg, UINT idEvent, DWORD dwTime);

	void	RemoveItem(LVITEM *item);

	void	StartEditTimer(int index, int col);
	void	StopEditTimer();

	HWND					hList;
	HIMAGELIST				hImage;
	HBRUSH					hBrushBg, hBrushHi;
	static WNDPROC			orgListViewProc, orgEditProc;
	TreeListViewDataFunc	dataFunc;
	TreeListViewNotifFunc	notifFunc;
	short					n_cols;
	char *					types;
	HWND					hEdit;
	int						edited_index, edited_col;
	int						timer_index, timer_col;
	int						selected_item_cur;
	void *					user_data;
	short *					widths;
	bool					acw_mode;
	bool					doing_acw;
};

