#define IMAGECLASS DockingImg
#define IMAGEFILE <Docking/Docking.iml>
#include <Draw/iml_header.h>

class DockCont;

class DockableCtrl : public ParentCtrl {
public:
	typedef DockableCtrl CLASSNAME;
	
	struct Style : ChStyle<Style> {
		Value handle[2];
		Rect handle_margins;
		bool handle_vert;
		Font title_font;
		Color title_ink[2];
		Value close[4];
		Value windowpos[4];
		Value autohide[4];
		Value pin[4];
		Value highlight[2]; // Opaque, transparent
	};	
	static const Style& StyleDefault();		
	static const Style& StyleDefaultVert();		

	enum { TIMEID_HIGHLIGHT = ParentCtrl::TIMEID_COUNT, TIMEID_COUNT };
private:
	Size			minsize;
	Size			maxsize;
	Size			stdsize;
	Image 			icon;
	WString 		title;
	String 			group;
	bool			dockable[4];
	dword			keycode;
	KeyInfo&(*		keyinfo)();

	const Style    *style;
	
	void			StopHighlight() 				{ Refresh(); }
protected:
	DockCont       *GetContainer() const;
public:
	Callback1<Bar&> WhenMenuBar;
	Callback		WhenState;

	virtual void WindowMenu(Bar& bar) 				{ WhenMenuBar(bar); }
	
	const Image& 	GetIcon()						{ return icon; }
	DockableCtrl& 	Icon(const Image& m);
	DockableCtrl& 	Title(const char *_title)		{ return Title((WString)_title); }
	DockableCtrl& 	Title(const WString& _title);
	const WString&  GetTitle()						{ return title; }

	DockableCtrl& 	Set(const Image& icon, const char *_title, String group = Null);
	DockableCtrl&	SetHotKey(dword key)			{ keycode = key; return *this; }
	DockableCtrl&	SetHotKey(KeyInfo&(*key)())		{ keyinfo = key; return *this; }
	bool			IsHotKey(dword key);

	DockableCtrl& 	SizeHint(const Size& min, const Size& max = Null, const Size& std = Null);
	void       		SetMinSize(Size sz) 			{ minsize = sz; }
	void       		SetMaxSize(Size sz) 			{ maxsize = sz; }	
	void 			SetStdSize(Size sz) 			{ stdsize = sz; }
	virtual Size	GetMinSize() const				{ return minsize; }
	virtual Size	GetMaxSize() const				{ return maxsize.IsNullInstance() ? Ctrl::GetMaxSize() : maxsize; }	
	virtual Size	GetStdSize() const				{ return stdsize.IsNullInstance() ? minsize : stdsize; }
		
	DockableCtrl& 	SetStyle(const Style& s)		{ style = &s; RefreshParentLayout(); return *this; }
	const Style& 	GetStyle()						{ return style ? *style : StyleDefault(); }
	
	virtual const String& GetGroup() const			{ return group; }
	virtual DockableCtrl& SetGroup(const String& g);
	
	DockableCtrl& 	AllowDockAll()					{ return AllowDockLeft().AllowDockRight().AllowDockTop().AllowDockBottom(); }
	DockableCtrl& 	AllowDockNone()					{ return AllowDockLeft(false).AllowDockRight(false).AllowDockTop(false).AllowDockBottom(false); }
	DockableCtrl& 	AllowDockLeft(bool v = true)	{ dockable[0] = v; return *this; }
	DockableCtrl& 	AllowDockTop(bool v = true)		{ dockable[1] = v; return *this; }
	DockableCtrl& 	AllowDockRight(bool v = true)	{ dockable[2] = v; return *this; }
	DockableCtrl& 	AllowDockBottom(bool v = true)	{ dockable[3] = v; return *this; }
	DockableCtrl& 	AllowDock(int a, bool v = true)	{ ASSERT(a >= 0 && a < 4); dockable[a] = v; return *this; }	
	bool			IsDockAllowed(int a) const		{ ASSERT(a >= 0 && a < 4); return dockable[a]; }
	bool            IsDockAllowedLeft() const  		{ return dockable[0]; }
	bool            IsDockAllowedTop() const  		{ return dockable[1]; }
	bool            IsDockAllowedRight() const  	{ return dockable[2]; }
	bool            IsDockAllowedBottom() const  	{ return dockable[3]; }
	bool            IsDockAllowedAny() const  		{ return dockable[0] || dockable[1] || dockable[2] || dockable[3]; }
	bool            IsDockAllowedNone() const  		{ return !IsDockAllowedAny(); } 
	
	bool 			IsFloating() const;
	bool 			IsDocked() const;
	bool 			IsAutoHide() const;
	bool 			IsTabbed() const;
	bool 			IsHidden() const;
	int 			GetDockAlign() const;
	
	void			Highlight();
	void			TimedHighlight(int ms);
	
	virtual Value 	GetSortValue() { return GetTitle(); }	

	DockableCtrl();
};

struct DockableParent : public DockableCtrl
{
	virtual void Paint(Draw& w) { w.DrawRect(GetSize(), SColorFace); }
};
