text: #include "DockCtrl/DockCtrl.h"
  
  #define IMAGEFILE <DockCtrl/DockableCtrl.iml>
  #define IMAGECLASS DockableCtrlImages
  #include <Draw/iml.h>
  
  //===============================================
  // DockableCtrl class:
  // Base class of all DockCtrl widgets.
  //===============================================
  
  DockableCtrl::DockableCtrl()
  {
  	DockingStyle(DOCK_NONE, STATE_SHUT, 0);
  	PermitDragAndDrop();
  	SetDropTarget();	
  	docksize.Clear();
  	hasdragbar	= false;
  	haschildbar	= false;
  	isdragged	= false;
  	isdraggable = true;
  	dockbase 	= NULL;
  	style		= NULL;
  	WhenClose	= THISBACK(OnShutWindow);
  	NoCenter().BackPaint();
  }
  
  DockableCtrl::~DockableCtrl()
  {
  }
  
  DockableCtrl& DockableCtrl::DockingStyle(int alignment, int state, int position)
  {
  	dockalignment 	= alignment;
  	dockstate		= state;
  	dockposition	= position;
  	return *this;
  }
  
  DockableCtrl& DockableCtrl::SetLabel(String title)
  {
  	IsNull(title) || title == t_("") ? dockname = t_("Untitled") :  dockname = title;
  	Title(title);
  	if(IsVisible()) Refresh();
  	return *this;
  }
  
  DockableCtrl& DockableCtrl::SetIcon(Image icon)
  {
  	dockicon = icon;
  	Icon(dockicon);
  	if(IsVisible()) Refresh();
  	return *this;
  }
  
  DockableCtrl& DockableCtrl::SetSize(Size sz)
  {
  	SetSizeHint(sz);
  	Rect r = GetRect();
  	SetRect(r.left, r.top, r.left + sz.cx, r.top + sz.cy);
  	if(IsFloating()) Refresh();
  	else RefreshParentLayout();
  	return *this;
  }
  
  void DockableCtrl::ReSize()
  {
  	docksize = Ctrl::GetSize();
  	for(int i = 0; i < GetFrameCount(); i++) Ctrl::GetFrame(i).FrameAddSize(docksize);	
  }
  
  void DockableCtrl::Layout()
  {
  	TopWindow::Layout(); 
  	if(IsFloating() && IsOpen()) ReSize();
  }
  
  void DockableCtrl::OpenWindow(Rect& r)
  {
  	if(IsPopUp()) Close();
  	if(IsOpen()) return;
  	ReSize();
  	r.right  = r.left + docksize.cx;
  	r.bottom = r.top  + docksize.cy;
  	HideDragBar();
  	Title(GetLabel());
  	SetRect(r);
  	Ctrl::Hide();
  	Open(GetOwner());
  	Ctrl::Show();
  	Refresh();
  }
  
  void DockableCtrl::OpenWindow(int x, int y, int cx, int cy)
  {
  	if(IsPopUp()) Close();
  	if(IsOpen()) return;
  	HideDragBar();
  	Title(GetLabel());
  	SetRect(x, y, cx, cy);
  	Ctrl::Hide();
  	Open(GetOwner());
  	Ctrl::Show();
  	Refresh();	
  }
  
  void DockableCtrl::ShutWindow()
  {
  	if(IsPopUp()) Close();
  	ReSize();
  	if(!IsOpen() || !IsFloating()) return;
  	Rect r 	 = GetRect();
  	r.right  = r.left + docksize.cx;
  	r.bottom = r.top  + docksize.cy;
  	Close();
  	Remove();
  	SetRect(r);  
  	ShowDragBar();
  }
  
  void DockableCtrl::OnShutWindow()
  {
  	Shut();
  }
  
  void DockableCtrl::ContextMenu()
  {
  	MenuBar::Execute(WhenContextMenu); 
  }
  
  void DockableCtrl::Settings()
  {
  	GetBase().ControlPanel();
  }
  
  void DockableCtrl::Menu()
  {
  	ContextMenu();
  }
  
  void DockableCtrl::StartWindowDrag()
  {
  	if(!isdraggable) return;
  	Point pt = GetMousePos();
  	Float();
  
  // Thanks to mrjt (James Thomas) for the X11 window drag code.	
  #if	defined(PLATFORM_WIN32)
  	SendMessage(GetHWND(), WM_NCLBUTTONDOWN, 2, MAKELONG(pt.x, pt.y));
  #elif defined(PLATFORM_X11)
  	Atom xwndDrag = XAtom("_NET_WM_MOVERESIZE");
  	XEvent e;
  	Zero(e);
  	e.xclient.type = ClientMessage;
  	e.xclient.message_type = xwndDrag;
  	e.xclient.window = GetWindow();
  	e.xclient.format = 32;
  	e.xclient.display = Xdisplay;
  	e.xclient.send_event = XTrue;
  	e.xclient.data.l[0] = pt.x;
  	e.xclient.data.l[1] = pt.y;
  	e.xclient.data.l[2] = 8;
  	e.xclient.data.l[3] = 1;
  	e.xclient.data.l[4] = 0;	
  	
  	XUngrabPointer(Xdisplay, CurrentTime);
  	XSendEvent(Xdisplay, RootWindow(Xdisplay, Xscreenno), XFalse, SubstructureNotifyMask, &e);
  	XFlush(Xdisplay);
  #endif
  }
  
  
  #if defined(PLATFORM_WIN32)
  LRESULT  DockableCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  {
  	if(IsFloating())
  	{
  		switch(message)
  		{
  			case WM_MOVING:
  					if(!isdraggable) break;
  					isdragged = true;
  					SetDropTarget(DOCK_NONE, GetDropState());
  					GetBase().DoDragAndDrop(*this, GetMousePos(), GetCtrlSize());
  					break;
  		
  			case WM_EXITSIZEMOVE:
  					if(!isdraggable) break;
  					if(!GetMouseLeft() && HasDropTarget() && isdragged) 
  					{
  						Dock(GetDropTarget(), GetDropState(), Position());
  						Refresh();
  						SetDropTarget();
  						isdragged = false;
  					}
  				break;
  			
  			case WM_NCRBUTTONDOWN:
  					ContextMenu();
  				return 1L;
  				
  			default:
  				break;
  		}
  	}
  	return TopWindow::WindowProc(message, wParam, lParam);
  }
  #elif defined(PLATFORM_X11)
  void DockableCtrl::EventProc(XWindow& w, XEvent *event)
  {
  	if (IsOpen()) 
  	{
  		switch(event->type) {
  		case ConfigureNotify:
  		{
  			if(!isdraggable) break;
  			XConfigureEvent& e = event->xconfigure;
  			if (Point(e.x, e.y) != GetScreenRect().TopLeft()) 
  			{
  				SetDropTarget(DOCK_NONE, GetDropState());
  				if(!isdragged);
  				{	
  					isdragged = true;
  					GetBase().DoDragAndDrop(*this, GetMousePos(), GetCtrlSize());
  					SetFocus();
  				}
  				break;
  			}
  			break;
  		}
  		case FocusIn:
  			if(!isdraggable) break;
  			XFocusChangeEvent &e = event->xfocus;
  			if (e.mode == NotifyUngrab) 
  			{
  				Dock(GetDropTarget(), GetDropState(), Position());
  				SetDropTarget();
  				isdragged = false;
  				return;
  			}
  			break;
  		}
  	}
  	TopWindow::EventProc(w, event);	
  }
  #endif
  