/////////////////////////////////////////////////////////////////////////////
// Name:        No names yet.
// Purpose:     Contrib. demo
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     2000/02/08
// RCS-ID:      $Id: pm.h,v 1.9 2001/04/23 00:44:15 georgetasker Exp $
// Copyright:   (c) Aleksandras Gluchovas
// Licence:   	GPL (version 2.0 or later)
/////////////////////////////////////////////////////////////////////////////

#ifndef __PM_G__
#define __PM_G__

#include "wx/pmf/pm_cmn.h"
#include "wx/pmf/pm_doc.h"
#include "wx/pmf/pm_docmgr.h"

class wxPMMenuItemData : public wxObject
{
public:
	wxPMMenuItemData() : m_pReceiver( NULL ),
						 m_ActualId(-1)
		{}
public:
	wxEvtHandler*         m_pReceiver;
	int                   m_ActualId;
};

// Listener interface for receiving service-management related
// notifications, those can occure even when the workplace 
// is not opened yet

class wxPMBootstrapServiceListener
{
public:
	virtual void OnServiceStarted( wxPMService& service );
	virtual void OnServiceStopped( wxPMService& service );

	virtual void OnPaneShown( wxPMPane& pane );
	virtual void OnPaneHidden( wxPMPane& pane );
};

class PMServiceAssociationInfo : public wxObject
{
public:
	~PMServiceAssociationInfo();

public:
	PMServiceListT mToServices;
	wxArrayPtrVoid mData;
};

/*
 * misc. NOTES: bootstrap is a special service is, the one which is 
 * always availabe, even if the workplace is not opened. It also
 * takes over menu-merging functionality, since it is needed
 * from the very start. Currently, the menu-merging alg. does not make 
 * use of wxMenu::Delete method, because (AFAIK) wxMenu/wxMenubar does not 
 * allow removing of top-level menus, and with it's API i cannot *insert* a 
 * single item at particular position a in top-level or -submenu. Instead, 
 * the alg. mirrors the entire tree of menus as in-memory structures, 
 * and uses them to recreate menu-bar whenever any changes or merges (even small 
 * ones) occure. TODO:: ask wx-developers...
 */

class wxPMBootstrapService : public wxEvtHandler, public wxPMService
{
public:
	wxPMBootstrapService( wxDocMDIParentFrame* pMainWnd, wxPMDocManager* pDocMgr );
	~wxPMBootstrapService();

	// closes all documents, removes related objects and releases itself
	// returns FALSE, if the any of the closure was veto'ed

	virtual bool CleanUp();

	virtual wxDocMDIParentFrame* GetMainWindow();
	virtual wxKeyBinder& GetKeyBinder();
	virtual void TranslateKeyEvent( wxKeyEvent& event );

	/// overriden methods of wxPMService ///
	virtual bool Start();
	virtual bool Stop();
	virtual wxPMMergableMenuChain* GetMergableMenuChain();
	virtual wxObject* GetWxObject();

	virtual void SetStatusText( const wxString& message );

	////////////////////////////////////////

	virtual void AddListener( wxPMBootstrapServiceListener* pListener );
	virtual void RemoveListener( wxPMBootstrapServiceListener* pListener );

	virtual const wxString& GetStartupDir();

	// sets currently opened workplace
	virtual void SetWorkplace( wxPMWorkplace* wp );
	virtual wxPMWorkplace* GetWorkplace();

	virtual bool HasWorkplace() { return m_pWorkplace != NULL; }

	virtual wxPMDocManager* GetDocManager();

	// service activation/disposal
	virtual void AddService( wxPMService* pSvc );
	virtual void StartService( wxPMService* pSvc );
	virtual wxPMService* FindServiceByClass( wxClassInfo* pExactSvcClass );
	virtual void StopService( wxPMService* pSvc );
	virtual void StopAllServices();
	virtual void RemoveAllServices();
	virtual void RemoveService( wxPMService* pSvc );
	virtual void DetachService( wxPMService* pSvc );
	virtual void FindServicesByClass( wxClassInfo* pSvcClass,
									  PMServiceListT& toLst, bool machSubclasses );

	// associating custom data with particular service,
	// invoked from wxPMService::AssociateData(..)

	virtual bool AssociateData( wxPMService& fromSerice, 
								wxPMService& toService,
								wxObject* pData );

	virtual wxObject* GetAssociatedData( wxPMService& fromService, 
										 wxPMService& toService );
								
	// registering instances which implement certain interface,
	// but can exist only as single object at run-time, so that
	// others services can find this distinct service. Interface
	// name should correspond to the real interface class name
	// which the service supports in it's QueryInterface(..)

	virtual bool RegisterUniqueServiceInstance( wxPMService* pSvc, const wxString& interfaceName );
	virtual bool UnregisterUniqueServiceInstance( wxPMService* pSvc, const wxString& interfaceName );
	virtual wxPMService* FindUniqueServiceInstance( const wxString& byInterfaceName );

	// displaying/hiding of panes
	virtual void ShowPane( wxPMPane* pPane );
	virtual void HidePane( wxPMPane* pPane );

	// meriging of menus into menubar of main window
	virtual void RemoveMenuChains( wxPMMergableMenuChain* pChains );
	virtual void MergeMenuChains( wxPMMergableMenuChain* pChains, wxEvtHandler* pOwner );

	// returns number of services actually removed
	virtual int RemoveServicesByClass( wxClassInfo* pSvcClass );
	virtual bool StartServicesByClass( wxClassInfo* pSvcClass );

	virtual void SetAppTitle( const wxString& appTitle );
	virtual wxString& GetAppTitle();

	// called by wxPMDocManager
	virtual void ActivateRelatedPanes( wxPMDocument* pDoc, bool activate );

	// event handlers

	void OnIdle( wxIdleEvent& event );      // used for updating menu-bar (batches multiple
											// menu-merges/removes into one to reduce flicker)

	void OnMenuEvent( wxEvent& event );	    // used for translation of event-ids to those
									       	// of "requested" by event-owners
	void OnButtonEvent( wxEvent& event );   // -/-
	void OnUpdateUIEvent( wxEvent& event ); // -/-

	/*** command-event handlers ***/

	void OnExit( wxCommandEvent& event );
	void OnAbout( wxCommandEvent& event );
	void OnDummy( wxCommandEvent& event );
	void OnOptionsEditorPrefs( wxCommandEvent& event );
	void OnOptionsDirectories( wxCommandEvent& event );
	void OnOptionsChangeCWD( wxCommandEvent& event );
	void OnOptionsKeyBindings( wxCommandEvent& event );

	// IDs which can be used by other services, for
	// translation of command-events to the boot-strap object

	enum COMMAND_IDS
	{
		ID_BOOTSTRAP_ON_EXIT = 20000, // it's because events of
									  // bootstrap svc. are handled directly
									  // (without translation)
//		ID_BOOTSTRAP_CHANGE_DIR,
		ID_BOOTSTRAP_ON_ABOUT,
		ID_BOOTSTRAP_ON_DUMMY,
		ID_BOOTSTRAP_OPTIONS_EDITOR_PREFS,
		ID_BOOTSTRAP_OPTIONS_DIRECTORIES,
		ID_BOOTSTRAP_OPTIONS_CHANGE_CWD,
		ID_BOOTSTRAP_OPTIONS_KEYBINDINGS
	};

	DECLARE_EVENT_TABLE()

protected:
	virtual void DoTranslateEvent( wxEvent& event );
	virtual wxCommandInfo* FindItemByName( const wxString& path );
	virtual wxCommandInfo* DoFindItemByName( const char* path, wxCommandInfoListT& lst );
	virtual void DoRemoveChain( wxPMMergableMenuChain* pChain );
	virtual void DoMergeChain( wxPMMergableMenuChain* pChain,
							   wxEvtHandler* pReceiver );
	virtual void MutateCommandToGroup( wxCommandInfoListT& lst, size_t cmdIdx );
	virtual wxCommandInfoListT* CreateTreePath( const wxString& path, wxCommandInfo*& pParent );
	virtual wxString StripLastPathItem( const wxString& treePath );
	virtual wxString GetPathItem( const wxString& treePath, size_t i );
	virtual void RemoveItemByPath( const wxString& treePath );
	virtual void DoRegenerateCommandIds( wxCommandInfoListT& commands, int& nextId );
	virtual void RegenerateCommandIds();

protected:
	wxPMWorkplace*		 m_pWorkplace; // opened workplace, NULL otherwise
	wxDocMDIParentFrame* m_pMainWnd;	  // not owned by bootstrap. svc
	wxPMDocManager*		 m_pDocMgr;	  // -/-

	PMServiceListT		 m_Services;	 // released outmatically when workplace is closed

	wxKeyBinder			 m_KeyBinder; // mirrors hierarchy of native menu items
									    // to which have not access with current wxWin API

	bool m_RecreatePending; // is set whenever content of menu-tree is changed,
						   // cleared when EVT_IDLE occures where menubar is recreated

	wxString			m_AppTitle;

	wxHashTable			m_MenuItemsHash;      // integer cmdId <-> wxCommandInfo
	wxHashTable			m_PerServiceDataHash; // serivce object <-> PMServiceAssociationInfo
	wxHashTable         m_UniqueInstHash;     // interfaceNames <-> unique service instances

	wxString			mStartupDir; // usually where config_* files reside

	PMBootstrapServiceListenerListT m_Listeners;
};

/* global  access-point to the single instance of bootstrap service */

void wxSetPMBootstrapSvc( wxPMBootstrapService* pSvc );

wxPMBootstrapService& wxGetPMBootstrapSvc();
wxPMBootstrapService& wxPMBootSvc(); // shorter-synonym

#endif // __PM_G__
