/**********************************************************************
 
	Copyright (C) 2003-2004
	Hirohisa MORI <joshua@nichibun.ac.jp>
	Tomoki SEKIYAMA <sekiyama@yahoo.co.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/



#ifndef ___V_TREE_VIEW_H___
#define ___V_TREE_VIEW_H___

#include "v/VObject.h"
#include "v/VTreeView.h"

// for bool typed data
void* const VTF_FALSE = 0;
void* const VTF_TRUE = (void*)-1;

// types of data
const char VTT_BOOL	= 'b';
const char VTT_TEXT	= 'c';
const char VTT_PERC	= 'p';
const char VTT_TYPE_MASK = 0x7f;
const char VTT_EDITABLE = 0x80;	// to be or-ed

const int v_tree_view_hash_size = 31;

class VTreeView;

class VTreeNode {
  public:
	VTreeNode(int cols);
	VTreeNode(int cols, const VTreeNode&);	// does not deep-copy **data
	~VTreeNode();	// does not delete **data
	
	void		*key;
	const void	**data;
	bool		editable;
  private:
	VTreeNode(VTreeNode&);	// no shallow copy
	VTreeNode	*next, *prev, *parent, *children;	// for ring
	VTreeNode	*h_next, *h_prev;	// for hash
	VTreeNodeInfo	info;
	
	friend class VTreeView;
	friend class VTreeViewImp;
};


class VTreeView : public VObject
{
  public:
	enum { object_type = VO_TREV };
	virtual unsigned	get_type() const { return object_type; }
	
	enum VTableViewAttr {
		select_none = 0x0,
		select_single = 0x1,
		select_multi = 0x2,
		selection_mask = 0x3,
		
		scrollbar_h = 0x10,
		scrollbar_v = 0x20,
		size_box_area = 0x40
	};

	struct tree_set {
		int		cols;
		char		*types;
		const L_CHAR	**title;
		short		*widths;
	};
	static VTreeView*	create(
				const VObjectStatus	*s,
				int				flags,
				int				cols,
				char			*types,
				const L_CHAR	**title,
				short			*widths,
				VExError*		err = 0) {
		tree_set set = {cols, types, title, widths};
		return create(s, flags, &set, err);
	}
	static VTreeView*	create(const VObjectStatus *s, int flags, void *arg, VExError *err) {
		return static_cast<VTreeView*>(
			create_tmp(internal_new, object_type, s, flags, err, arg));
	}
	
	virtual VExError	get_status(VObjectStatus *, int flags) const;
	virtual VExError	set_status(const VObjectStatus *, int flags);
	
	virtual void		redraw(VRect* rect = 0) const;
	
	struct Selection {
		int		n;
		void	**keys;
		Selection(int n = 0) : n(n)	{ }
		~Selection()	{ if ( n )	delete keys; }
	};
	Selection *			get_selection() const;	// returned value must be deleted by user
	virtual void		set_select_event_handler(V_CALLBACK(handler), void *user_arg) {
		select_event_handler = handler;
		this->user_arg_select = user_arg;
	}
	// called from OS on row(s) selected
	static void			select_event(VTreeView *view, Selection* sel);
	
	struct RowEdit {
		VTreeNode	*node;
		int		col;
		const void	*data;
	};
	virtual void		set_row_edit_event_handler(V_CALLBACK(handler), void *user_arg) {
		row_edit_event_handler = handler;
		this->user_arg_row_edit = user_arg;
	}
	// called from OS on row(s) edited
	static void			row_edit_event(VTreeView *view, RowEdit *re);
	virtual void		row_edit_event_done(RowEdit *re);
	
	virtual VExError	add_row(VTreeNode *node, void *parent_key = 0, void *next_key = 0);
	virtual VExError	remove_row(void *key);
	virtual VTreeNode *	get_row(void *key) const;	// returned value must be deleted by user
	virtual VExError	set_row(VTreeNode *node);
	
	virtual int		get_n_cols() const { return cols; }
	virtual char*		get_types() const { return types; }
	
	void			debug_print(int depth=0, VTreeNode *node=0);
	
  protected:
	virtual ~VTreeView();
	
	virtual VExError	create_do(const VObjectStatus *, int flags,
					VObject * nmp, void * arg);
	virtual void		destroy_do(VObject*);
	
	// internal ring/hash accessor (must be called in msequence)
	virtual bool		add_node(VTreeNode **_node, void *parent_key, void *next_key);
	virtual void		remove_node(VTreeNode *node);
	virtual VTreeNode *	get_node(void *key) const;
	virtual bool		set_node(VTreeNode **_node);
	static Selection *	copy_selection(const VTreeView *view);
	
	V_CALLBACK(select_event_handler);
	void	*user_arg_select;
	
	V_CALLBACK(row_edit_event_handler);
	void	*user_arg_row_edit;
	

	int		cols;
	char		*types;
	VTreeNode	*ring;
	VTreeNode	**hash;
	Selection	*selection;
	VSemaphore	data_sem;
	
  private:
	static VObject *internal_new(){
		return new VTreeView();
	}
	
	friend class VTreeViewImp;
};

#include "machine/v_tree_view_m.h"

#endif
