#ifndef _COMMON_MDIFRM_HPP_
#define _COMMON_MDIFRM_HPP_
#ifndef _COMMON_STRING_HPP_
#include <common/string.hpp>
#endif
#ifndef _COMMON_PUREMENU_HPP_
#include <common/puremenu.hpp>
#endif
#ifndef _COMMON_GUIWINDOW_HPP_
#include <common/guiwnd.hpp>
#endif
#ifndef _COMMON_SMARTPOINTER_HPP_
#include <common/pointer.hpp>
#endif
#ifndef _COMMON_ARRAY_HPP_
#include <common/array.hpp>
#endif
#ifndef _COMMON_BLOCK_HPP_
#include <common/block.hpp>
#endif

class MDIWindow;

class FrameWindow : public GUIWindow
{
public:
	FrameWindow(void);
	virtual ~FrameWindow();
  void createWindow(const String &className,const String &windowName=String(),const String &menuName=String(),const String &iconName=String());
	Window &getClient(void);
  bool getActive(SmartPointer<MDIWindow> &mdiWindow);
	bool getDocument(const String &strWindowName,SmartPointer<MDIWindow> &mdiWindow);
	bool getDocuments(Array<SmartPointer<MDIWindow> > &mdiWindows);
	bool getDocumentClass(const String &strClassName,SmartPointer<MDIWindow> &mdiWindow);
  void enableMenuItems(UINT menuIndex,UINT itemID,PureMenu::PositionFlags positionFlags,PureMenu::InsertFlags insertFlags);
	PureMenu &getFrameMenu(void);
	void insert(MDIWindow &mdiWindow);
	MDIWindow &operator[](int winIndex);
	void destroy(void);
	int size(void)const;
	void cascade(void)const;
	void tile(void)const;
	void arrange(void)const;
	void closeAll(void)const;
	void restoreAll(void)const;
	void minimizeAll(void)const;
	BOOL activate(UINT childIndex);
protected:
  virtual bool preDestroy(MDIWindow &mdiWindow);
	virtual void preRegister(WNDCLASS &wndClass);
	virtual void mdiDestroy(MDIWindow &mdiWindow);
	virtual void mdiDeactivate(MDIWindow &mdiWindow);
	virtual void mdiActivate(MDIWindow &mdiWindow);
	virtual void moreWindows(void);
private:
  enum{IDFirstMDIChild=100};
	enum{MDICloseAll,MDIRestoreAll,MDIMinimizeAll};
	CallbackData::ReturnType destroyHandler(CallbackData &someCallbackData);
	CallbackData::ReturnType mdiActivateHandler(CallbackData &someCallackData);
	CallbackData::ReturnType commandHandler(CallbackData &someCallbackData);
  FrameWindow(const FrameWindow &frameWindow);
	FrameWindow &operator=(const FrameWindow &frameWindow);
	int windowProcedure(HWND hWnd,WORD message,WPARAM wParam,LPARAM lParam);
  void registerClass(HINSTANCE hInstance,const String &className,const String &iconName);
	void createMDIClientWindow(void);
  void watchDocumentWindows(void);
#if defined(_MSC_VER)
	__declspec(dllexport) static int FAR PASCAL enumerateProcedure(HWND hWnd,LPARAM lParam);
#else
	static int FAR PASCAL _export enumerateProcedure(HWND hWnd,LPARAM lParam);
#endif

	PureMenu mFrameMenu;
	Window mClientWnd;
	Callback<FrameWindow> mDestroyHandler;
	Callback<FrameWindow> mMDIActivateHandler;
	Callback<FrameWindow> mCommandHandler;
	Block<SmartPointer<MDIWindow> > mDocuments;
};

inline
Window &FrameWindow::getClient(void)
{
  return mClientWnd;
}

inline
PureMenu &FrameWindow::getFrameMenu(void)
{
  return mFrameMenu;
}

inline
void FrameWindow::cascade(void)const
{
  if(!mClientWnd.isValid())return;
	mClientWnd.sendMessage(WM_MDICASCADE,0,0L);
}

inline
void FrameWindow::tile(void)const
{
  if(!mClientWnd.isValid())return;
	mClientWnd.sendMessage(WM_MDITILE,0,0L);
}

inline
void FrameWindow::arrange(void)const
{
  if(!mClientWnd.isValid())return;
	mClientWnd.sendMessage(WM_MDIICONARRANGE,0,0L);
}

inline
void FrameWindow::closeAll(void)const
{
  ::EnumChildWindows(mClientWnd,(WNDENUMPROC)enumerateProcedure,MAKELONG(MDICloseAll,0));
}

inline
void FrameWindow::minimizeAll(void)const
{
  ::EnumChildWindows(mClientWnd,(WNDENUMPROC)enumerateProcedure,MAKELONG(MDIMinimizeAll,0));
	mClientWnd.sendMessage(WM_MDIICONARRANGE,0,0L);
}

inline
void FrameWindow::restoreAll(void)const
{
  ::EnumChildWindows(mClientWnd,(WNDENUMPROC)enumerateProcedure,MAKELONG(MDIRestoreAll,0));
	mClientWnd.sendMessage(WM_MDICASCADE,0,0L);
}
#endif
