/*	XMenu.h
 *
 *		This contains the various menu handling classes. Both the
 *	Macintosh and Windows use an abstraction of a 'menu', so this
 *	wrappers that abstraction.
 */

/*  YAAF - Yet another application framework
 *  Copyright (C) 1997, 1998 William Edward Woody
 *  
 *  This library is free software; you can redistribute it
 *  and/or modify it under the terms of the GNU Library
 *  General Public License as published by the Free Software
 *  Foundation; either version 2 of the License, or any
 *  later version.
 *  
 *  This library is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABIILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE. See the GNU Library General Public License for
 *  more details.
 *  
 *  You should have received a copy of the GNU Library General
 *  Public License along with this library; if not, write to the
 *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#ifndef PandaWave_XMENU
#define PandaWave_XMENU

#include <XConfig.h>
#include <XDynArray.h>
#include <XHandle.h>

#if OPT_XWIN
#include <X11/Xlib.h>						// X specific
#endif

/************************************************************************/
/*																		*/
/*	Class References													*/
/*																		*/
/************************************************************************/

class XGFocus;

/************************************************************************/
/*																		*/
/*	Internal structures													*/
/*																		*/
/************************************************************************/

#if OPT_XWIN == 1

/*	XGSMenuItem
 *
 *		How a single item is stored in my XGMenu object. This is the data
 *	that is stored in the 'extra' data field of the XGStringList object.
 */

struct XGSMenuItem {
	short				fItemID;
	short				fAccelerator;
	short				fCheckmark;
	short				fEnabled;
};

#endif

/************************************************************************/
/*																		*/
/*	Menu Bar Objects													*/
/*																		*/
/************************************************************************/

/*	@C"XGMenu"
 *	@H"XMenu.h"
 *	@I
 *
 *		This defines a single menu. This is an abstraction for a single
 *	menu in the menu bar.
 */

class XGMenu {
	public:
		/*
		 *	Custom Construction
		 */
		
#if OPT_MACOS == 1
								XGMenu(MenuHandle, bool dup = false);
#endif

#if OPT_WINOS == 1
								XGMenu(HMENU);
#endif

#if OPT_XWIN
								XGMenu(unsigned char **);
#endif

		virtual					~XGMenu();
				
		/*
		 *	Menu attributes
		 */
		
		long					GetLength() const;
		void					InsertItem(long index);
		void					DeleteItem(long index);
		
		/*
		 *	Item attributes
		 */

		void					GetText(long index, char *str) const;
		void					SetText(long index, const char *str);
		short					GetItemID(long index) const;
		void					SetItemID(long index, short);
		XGMenu					*GetSubMenu(long index) const;
									
		/*
		 *	Check/Select attributes
		 */
		
		void					SetEnabled(long index, bool flag);
		void					SetCheckmark(long index, short mark);

	private:
		XGPDynArray<XGMenu>		fMenuList;

#if OPT_MACOS == 1
		bool					fDuplicate;
		MenuHandle				fMenuHandle;
		XGSDynArray<short>		fMenuItemID;
#endif

#if OPT_WINOS == 1
		bool					fInstalled;
		HMENU					fMenuHandle;
#endif

#if OPT_XWIN == 1
		short					GetCommand(char accel);
		XGStringList			fMenuData;
	friend class XGMenuPop;						// support for drawing
#endif

	friend class XGMenuBar;
};

/*	@C"XGMenuBar"
 *	@H"XMenu.h"
 *	@I
 *
 *		This is the menu bar object. This is the abstraction of the
 *	menu bar inside of my application. This is attached to the window
 *	or is global, and cannot be swapped out with another one like me.
 */

class XGMenuBar {
	public:
	
		/*
		 *	Custom constructors that are OS dependant
		 */
	
#if OPT_MACOS == 1
								XGMenuBar();
#endif

#if OPT_WINOS == 1
								XGMenuBar(HWND,bool);
#endif

#if OPT_XWIN == 1
								XGMenuBar(Window);
#endif

		virtual					~XGMenuBar();
		
		
		/*
		 *	Top level menus
		 */
		 
		//@G"Top Level Access"
		
		/*	@F"XGMenuBar::GetLength" @I
		 *
		 *		Gets the number of menus in this menu bar.
		 */
		
		long					GetLength() const
									{
										return fMenuBar.Length();
									}
									
		/*	@F"XGMenuBar::GetMenu" @I
		 *
		 *		Gets the specified menu. The index is zero based
		 */
		
		XGMenu					*GetMenu(long i) const
									{
										return fMenuBar[i];
									}
									
		char					GetAccelerator(short) const;
		void					SetAccelerator(short,char);
		
		bool					LoadFromResource(short);

		/*
		 *	Menu command processing
		 */
		
		void					UpdateMenuBar(XGFocus *);

#if (OPT_MACOS == 1)
		bool					MenuSelect(XGFocus *, short, short);
		bool					MenuCommand(XGFocus *, long);
#endif

#if (OPT_MACOS == 1) || (OPT_XWIN == 1)
		bool					MenuKey(XGFocus *, char);
#endif

#if (OPT_WINOS == 1)
		bool					MenuCommand(XGFocus *, WPARAM);
		static int				TranslateAccelerator(HWND,LPMSG);
#endif

#if OPT_XWIN == 1
		bool					MenuDispatch(XGFocus *, short);
		void					GetMenuName(short i, char *data)
									{
										fMenuList.GetString(i,data);
									}
#endif

	private:
	
		/*
		 *	Internal stuff for management
		 */
		
		short					fMenuBarID;
		bool					fMark;
		XGPDynArray<XGMenu>		fMenuBar;
		
		void					UpdateMenu(XGMenu *, XGFocus *);
		static XGMenu			*FindByCommand(XGMenu *, short, short *);
		XGMenu					*FindByCommand(short,short *) const;
		
#if OPT_MACOS == 1
		static XGMenu			*FindByMenuID(XGMenu *, short);
		XGMenu					*FindByMenuID(short) const;
#endif

#if OPT_WINOS == 1
		bool					fMDIFlag;
		HWND					fWindow;
		static HACCEL			gAccel;
		static bool				gAccelRes;
		static long				gAccelRef;
#endif

#if OPT_XWIN == 1
		XGStringList			fMenuList;
		Window					fWindow;
#endif
};

#endif /* PandaWave_XMENU */
