#ifndef _COMMON_PUREMENU_HPP_
#define _COMMON_PUREMENU_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_WINDOW_HPP_
#include <common/window.hpp>
#endif
#ifndef _COMMON_DWINDOW_HPP_
#include <common/dwindow.hpp>
#endif
#ifndef _COMMON_STRING_HPP_
#include <common/string.hpp>
#endif
#ifndef _COMMON_GDIPOINT_HPP_
#include <common/gdipoint.hpp>
#endif
#ifndef _COMMON_MENUITEM_HPP_
#include <common/menuitem.hpp>
#endif
#ifndef __FLAT__
#ifndef TPM_BOTTOMALIGN
#define TPM_BOTTOMALIGN 0x0020
#endif
#ifndef TPM_TOPALIGN
#define TPM_TOPALIGN    0x0000
#endif
#ifndef TPM_RETURNCMD
#define TPM_RETURNCMD   0x0100
#endif
#endif

class PureBitmap;

class PureMenu
{
public:
	enum InsertFlags{ItemBitmap=MF_BITMAP,ItemOwnerDraw=MF_OWNERDRAW,ItemString=MF_STRING,
				 ItemChecked=MF_CHECKED,ItemDisabled=MF_DISABLED,ItemEnabled=MF_ENABLED,
				 ItemGrayed=MF_GRAYED,ItemMenuBarBreak=MF_MENUBARBREAK,ItemMenuBreak=MF_MENUBREAK,
				 ItemPopup=MF_POPUP,ItemSeparator=MF_SEPARATOR,ItemUnchecked=MF_UNCHECKED,
				 ItemMouseSelect=MF_MOUSESELECT,ItemHilite=MF_HILITE,ItemSysMenu=MF_SYSMENU};
	enum PositionFlags{ByCommand=MF_BYCOMMAND,ByPosition=MF_BYPOSITION};
	enum TrackFlags{RightAlign=TPM_RIGHTALIGN,CenterAlign=TPM_CENTERALIGN,LeftAlign=TPM_LEFTALIGN,
				 BottomAlign=TPM_BOTTOMALIGN,TopAlign=TPM_TOPALIGN,ReturnCommand=TPM_RETURNCMD,
				 LeftButton=TPM_LEFTBUTTON,RightButton=TPM_RIGHTBUTTON};
  enum MenuType{TypeBitmap=MFT_BITMAP,TypeMenuBarBreak=MFT_MENUBARBREAK,TypeMenuBreak=MFT_MENUBREAK,
	       TypeOwnerDraw=MFT_OWNERDRAW,TypeRadioCheck=MFT_RADIOCHECK,TypeSeparator=MFT_SEPARATOR,
				 TypeString=MFT_STRING,TypeRightJustify=MFT_RIGHTJUSTIFY};
	enum MenuStyle{PopupMenu,BarMenu};
	PureMenu(void);
	PureMenu(MenuStyle menuStyle);
	PureMenu(HMENU hMenu);
	PureMenu(const PureMenu &somePureMenu);
	virtual ~PureMenu();
	operator HMENU(void)const;
	PureMenu &operator=(const PureMenu &somePureMenu);
	PureMenu &operator=(const String &menuName);
	PureMenu &operator=(HMENU hMenu);
	BOOL operator==(const PureMenu &somePureMenu)const;
	BOOL getSubMenu(int menuItemPos,PureMenu &subMenu)const;
	String menuItemString(UINT menuItem,PositionFlags positionFlags=ByPosition)const;
  UINT menuItemStringPos(const String &strMenuHeading)const;
  WORD enableMenuItem(UINT menuItem,PositionFlags positionFlags,InsertFlags insertFlags)const;
  bool checkMenuItem(UINT menuItem,UINT flags)const;
	UINT getMenuState(UINT menuItem,PositionFlags positionFlags)const;
  BOOL removeMenu(UINT position,PositionFlags positionFlags)const;
	WORD appendMenu(UINT itemID,const String &itemString)const;
	WORD appendMenu(Block<MenuItem> &menuItems)const;
	WORD appendSeparator(void)const;
	BOOL insertMenu(UINT position,InsertFlags insertFlags,UINT itemID,const String &itemString)const;
  BOOL insertMenu(UINT position,const PureMenu &pureMenu,const String &itemString)const;
  BOOL insertMenu(UINT position,const PureMenu &pureMenu,PureBitmap &somePureBitmap)const;
	WORD trackPopupMenu(const Window &parentWindow,const GDIPoint &trackPoint,DWORD trackFlags=TopAlign|LeftAlign)const;
	WORD trackPopupMenu(const DWindow &parentWindow,const GDIPoint &trackPoint,DWORD trackFlags=TopAlign|LeftAlign)const;
	WORD trackPopupMenu(HWND hParentWnd,const GDIPoint &trackPoint,DWORD trackFlags=TopAlign|LeftAlign)const;
	WORD isMenuItem(UINT itemID)const;
  MenuType getMenuItemType(UINT menuItem,PositionFlags positionFlags)const;
	WORD size(void)const;
	BOOL isOkay(void)const;
private:
  enum Disposition{Keep,Delete,Invalid};
	UINT menuItemID(WORD menuItemIndex)const;
	void createMenu(void);
	void destroyMenu(void);

	HMENU mhPureMenu;
	Disposition mDisposition;
	MenuStyle mMenuStyle;
};

inline
PureMenu::PureMenu(void)
: mhPureMenu(0), mDisposition(Delete), mMenuStyle(PopupMenu)
{
}

inline
PureMenu::PureMenu(MenuStyle menuStyle)
: mhPureMenu(0), mDisposition(Delete), mMenuStyle(menuStyle)
{
	createMenu();
}

inline
PureMenu::PureMenu(const PureMenu &somePureMenu)
: mhPureMenu(0), mDisposition(Delete)
{
	*this=somePureMenu;
}

inline
PureMenu::PureMenu(HMENU hMenu)
: mhPureMenu(hMenu), mDisposition(Keep)
{
}

inline
PureMenu::~PureMenu()
{
	destroyMenu();
}

inline
PureMenu::operator HMENU(void)const
{
  return mhPureMenu;
}

inline
BOOL PureMenu::operator==(const PureMenu &somePureMenu)const
{
  return mhPureMenu==somePureMenu.mhPureMenu;
}

inline
BOOL PureMenu::removeMenu(UINT position,PositionFlags positionFlags)const
{
  if(!isOkay())return FALSE;
	return ::RemoveMenu(mhPureMenu,position,(UINT)positionFlags);
}

inline
WORD PureMenu::appendMenu(UINT itemID,const String &itemString)const
{
	if(!isOkay())return FALSE;
	return ::AppendMenu(mhPureMenu,ItemString|ItemEnabled,itemID,(LPSTR)itemString);
}

inline
WORD PureMenu::appendSeparator(void)const
{
  if(!isOkay())return FALSE;
	return ::AppendMenu(mhPureMenu,ItemSeparator,0,"");
}

inline
UINT PureMenu::menuItemID(WORD menuItemIndex)const
{
	if(!isOkay())return FALSE;
	if(!isOkay()||menuItemIndex>=size())return FALSE;
	return ::GetMenuItemID(mhPureMenu,menuItemIndex);
}

inline
WORD PureMenu::trackPopupMenu(const Window &parentWindow,const GDIPoint &trackPoint,DWORD trackFlags)const
{
	return trackPopupMenu((HWND)parentWindow,trackPoint,trackFlags);
}

inline
WORD PureMenu::trackPopupMenu(const DWindow &parentWindow,const GDIPoint &trackPoint,DWORD trackFlags)const
{
	return trackPopupMenu((HWND)parentWindow,trackPoint,trackFlags);
}

inline
BOOL PureMenu::isOkay(void)const
{
  return ::IsMenu(mhPureMenu);
}
#endif

