/****************************************************************************************

		IPropertiesModule.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Greg
		Date:	8/5/98
		

		Revision History

		when		who			what & why
		==========	==========	======================================================
		9/1/98		Eml			Changed GUIDs, first int32 had 9 hex digits
		8/20/98		Greg		Added IPropertiesClient interface and removed
								LoadPropertiesPages() from IPropertiesModule

*****************************************************************************************/
#ifndef __IPROPERTIESMODULE__
#define __IPROPERTIESMODULE__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "COMTypes.h"
#include "MFPartTypes.h"
#include "MCPtr.h"


struct IMFPart;
struct IMFResponder;
struct IMFTabPart;
struct ISceneDocument;
struct I3DShModule;
struct IPropertiesClient;
struct IChangeChannel;
struct IMFSplitBarPart;

template<class T> class TMCClassArray;

#define kNoSelection			'****'

//******************************************************************
MCDEFINE_GUID(IID_IPropertiesModule, 0xb3240036, 0x41e1, 0x11d2, 0x8f, 0x42, 0x0, 0x60, 0x97, 0x98, 0xe7, 0x7d);
MCDEFINE_GUID(IID_IPropertiesClient, 0xb3240037, 0x41e1, 0x11d2, 0x8f, 0x42, 0x0, 0x60, 0x97, 0x98, 0xe7, 0x7d);

//******************************************************************

/// \addtogroup ShellInterface
/// \{

/// This interface is implemented by the properties module, the holder for properties information.  
/// It is also an I3DShModule.  It hosts various IPropertiesClient parts. 
struct IPropertiesModule : public IMCUnknown
{
	/// \param invalClientPages will trigger a full rebuild of the properties.
	///							set it to false when only the panel content need to be refreshed	
	virtual void		MCCOMAPI	Invalidate(boolean invalClientPages) = 0;
	virtual boolean		MCCOMAPI	IsValid() = 0;
	virtual void		MCCOMAPI	Validate() = 0;

	// ****************************************************************************
	//								SetCurrentClient
	// 
	/// Call SetCurrentClient() to attach your client to the properties module
	/// 
	/// \param inClient  Pointer to the client to attach to this module
	/// 
	virtual	void 		MCCOMAPI	SetCurrentClient(IPropertiesClient* inClient) = 0;

	// ****************************************************************************
	//								SetCurrentSelectionType
	// 
	/// Call SetCurrentSelectionType() when the type of selection changes so the properties
	/// module can save the preferred page for this selection type
	///
	/// \param inSelectionType  ID of the current selected object type
	/// 
	virtual void		MCCOMAPI	SetCurrentSelectionType(IDType inSelectionType) = 0;
	virtual IDType		MCCOMAPI	GetCurrentSelectionType() = 0;

	virtual MCCOMErr	MCCOMAPI	GetTabs(IMFTabPart** outTabPart) = 0;
	virtual MCCOMErr	MCCOMAPI	GetHostPart(IMFPart** outHostPart) = 0;
	virtual	ISceneDocument*		MCCOMAPI	GetDocumentNoAddRef() = 0;

	//IPropertiesModule also supports the I3DShModule interface
	virtual I3DShModule*		MCCOMAPI	GetThisModule() = 0;

	//Sets the title displayed at the top of the properties
	virtual void		MCCOMAPI	SetTitle(const TMCString& inTitle) = 0;

	// ****************************************************************************
	//								RepositionExtraPart
	// 
	/// Adjust the tabs to make room for the extra part
	/// Call this only if you need to change the extra part's size several times.
	/// 
	virtual void		MCCOMAPI	RepositionExtraPart		() = 0;
};

//******************************************************************

#define kPreviewTabNodeID 999

/// TPropertyTab contains the information given to the properties module by the client 
/// to load the tabs that are independent from the current selection (through GetExtraTabs)
///
/// Note that the fCompFamilyID, fCompClassID and fNodeID are used to identify the tab 
///	to avoid annoying change of the current tab when the selection changes.
///	(they won't be used to override fPage if you provide a part for it)
///
/// Example of implementation of GetExtraTabs:
/// \code
///		extraTabs.SetElemSpace(4);
///		extraTabs.AddElem( TPropertyTab(kRID_ModuleFamilyID, kHierModuleID, kHierarchyTreeNodeID,	kHierarchyModulePublicStrings, kHierModuleInstancesString) );
///		extraTabs.AddElem( TPropertyTab(kRID_ModuleFamilyID, kHierModuleID, kObjectsPartNodeID,		kHierarchyModulePublicStrings, kHierModuleObjectsString) );
///		extraTabs.AddElem( TPropertyTab(kRID_ModuleFamilyID, kHierModuleID, kShadersPartNodeID,		kHierarchyModulePublicStrings, kHierModuleShadersString) );
///		TPropertyTab previewTab(kRID_ModuleFamilyID, k3DViewModuleClassID, kPreviewTabNodeID, k3DViewModulePublicStrings, k3DViewModulePreviewString);
///		previewTab.fPage= gShell3DUtilities->GetScenePreviewPart();
///		extraTabs.AddElem(previewTab);
/// \endcode
struct TPropertyTab
{
	TMCPtr<IMFPart>		fPage;				///<The node part to display 
	TMCDynamicString	fTitle;				///<The tab's title

	//If you do not want to load fPage and/or fTitle you can fill the following fields
	IDType				fCompFamilyID;		///<To setup the correct resource file
	IDType				fCompClassID;		///<To setup the correct resource file
	MFPartID			fNodeID;			///<ID of the node part to use for the page
	int16 				fTitleResID;		///<ID of the STR# resource to use for the title
	int16 				fTitleResIndex;		///<index (one based) of the title in the STR# resource
	

	TPropertyTab		()												{ Init(); }
	TPropertyTab		(const TPropertyTab& tab)
	{
		fPage			= tab.fPage;
		fTitle			= tab.fTitle;
		fCompFamilyID	= tab.fCompFamilyID;	 
		fCompClassID	= tab.fCompClassID;
		fNodeID			= tab.fNodeID;
		fTitleResID		= tab.fTitleResID;
		fTitleResIndex	= tab.fTitleResIndex;
	}

	TPropertyTab		(IMFPart* inPage, const TMCString& inTitle)
	{ 
		Init(); 
		fPage	= inPage;
		fTitle	= inTitle;
	}

	TPropertyTab		(IDType familyID, IDType classID, MFPartID nodeID, int16 titleResID, int16 titleResIndex)
	{
		fCompFamilyID	= familyID;	 
		fCompClassID	= classID;
		fNodeID			= nodeID;
		fTitleResID		= titleResID;
		fTitleResIndex	= titleResIndex;
	}

	void Init()
	{
		fCompFamilyID	= 0;	 
		fCompClassID	= 0;
		fNodeID			= 0;
		fTitleResID		= 0;
		fTitleResIndex	= 0;
	}
};


/// The properties client that hosts the properties of the current selected object.  The properties are displayed as
/// one or more tabs.  Above the tabs, an optional "Extra Part" can be displayed.
struct IPropertiesClient : public IMCUnknown
{
	// ****************************************************************************
	//								GetSelectionChannel
	// 
	/// Called when the properties module needs to know the selection channel associated
	/// with this client.  <B>Note:</B> remember to AddRef outChannel before returning!
	/// 
	/// \param outChannel  
	/// 
	virtual void		MCCOMAPI	GetSelectionChannel(IChangeChannel** outChannel) = 0;

	// ****************************************************************************
	//								GetControllingModuleID
	// 
	/// Called when the properties module needs to know the ID of the controlling module.
	/// This is used to set up component resources, etc.
	/// 
	virtual IDType		MCCOMAPI	GetControllingModuleID() = 0;

	// ****************************************************************************
	//								GetPropResID
	// 
	/// This is called when the selection changes, and should return the resource ID of the 'Prop' resource containing the pages to be loaded.
	/// 
	/// 
	virtual ResourceID	MCCOMAPI	GetPropResID() = 0;

	// ****************************************************************************
	//								GetToolPropResID
	// 
	/// This is called when a tool changes, and should return the resource ID of the 'Prop' resource containing the pages to be loaded.
	/// 
	/// 
	virtual ResourceID	MCCOMAPI	GetToolPropResID() = 0;

	// ****************************************************************************
	//								GetToolTabSize
	// 
	/// Returns the size of the tool tabs (or 0 if not visible).
	/// 
	/// 
	virtual int32		MCCOMAPI	GetToolTabSize() = 0;

	// ****************************************************************************
	//								LoadPageData
	// 
	/// This is called when the Properties Client's pages need to be loaded.
	/// 
	/// \param inTopPart  Pointer to the Part that will hold the pages.
	/// 
	virtual void		MCCOMAPI	LoadPageData(IMFPart* inTopPart) = 0;

	// ****************************************************************************
	//								LoadToolPageData
	// 
	/// This is called when the Properties Client's tool pages need to be loaded.
	/// 
	/// \param inTopPart  Pointer to the Part that will hold the pages.
	/// 
	virtual void		MCCOMAPI	LoadToolPageData(IMFPart* inTopPart) = 0;

	// ****************************************************************************
	//								HandlePageHit
	// 
	/// This is called when a user event happens inside the client's pages (e.g. a slider
	/// moved or a text edit field was validated).  This function is similar to IMFExResponder::Receive()
	/// (the last three arguments are the same), and should take the appropriate changed data and 
	/// post an undoable action to make the change in the selection.
	/// 
	/// \param inTopPart    Pointer to host part in which the Properties Client sits.
	/// \param inMessage    Message passed by the event.  See EMFPartMessage
	/// \param inResponder  Pointer to responder that initiated the event.
	/// \param inData       Data passed along with the event.
	/// \return true if the event has been handled, and false otherwise.
	/// 
	virtual boolean		MCCOMAPI	HandlePageHit(IMFPart* inTopPart, int32 inMessage, IMFResponder* inResponder, void* inData) = 0;

	// ****************************************************************************
	//								HandleToolPageHit
	// 
	/// This is called when a user even happens inside the client's tool pages (e.g. a slider
	/// moved or a text edit field was validated).  This function is similar to IMFExResponder::Receive()
	/// (the last three arguments are the same), and should take the appropriate changed data and 
	/// post an undoable action to make the change in the selection.
	/// 
	/// \param inTopPart    Pointer to host part in which the Properties Client sits.
	/// \param inMessage    Message passed by the event.  See EMFPartMessage
	/// \param inResponder  Pointer to responder that initiated the event.
	/// \param inData       Data passed along with the event.
	/// \return true if the event has been handled, and false otherwise.
	/// 
	virtual boolean		MCCOMAPI	HandleToolPageHit(IMFPart* inTopPart, int32 inMessage, IMFResponder* inResponder, void* inData) = 0;

	// GetExtraPart() is called when the properties module needs the 
	// extra part that should be placed above the tabs part in the properties
	// window.  If you do not want any extra part, return NULL in outExtraPart.
	// NOTE: the properties module will handle the addition and removal of the part from the host
	// the host---however, the properties client is in charge of calling CallPrepareToDestroy
	// (typically when you are destroyed, so keep a reference to it.
	// Note: the Extrapart should have left and right constrains to be properly refreshed when the 
	// drawer is opened.
	// ****************************************************************************
	//								GetExtraPart
	// 
	/// This is called when the properties module needs the extra part that will be 
	/// placed above the tabs part in the properties window.  If you do not want any extra
	/// part, return NULL in outExtraPart.
	/// \note The properties module will handle the addition and removal of the part from the host - 
	/// however, the properties client is in charge of calling CallPrepareToDestroy (typically
	/// when it is destroyed), so keep a reference to the extra part.
	/// \note The Extra Part should have left and right constraints so that it is properly refreshed when the drawer is opened.
	/// 
	/// \param outExtraPart  Returns a pointer to the extra part.
	/// 
	virtual void		MCCOMAPI	GetExtraPart(IMFPart** outExtraPart) = 0;

	// ****************************************************************************
	//								GetExtraTabs
	// 
	/// Returns the list of the extra tabs that are to be displayed under the regular properties tabs.
	/// 
	/// \param extraTabs  Returns the additional tabs to be displayed under the regular properties tabs.
	/// 
	virtual void		MCCOMAPI	GetExtraTabs(TMCClassArray<TPropertyTab>& extraTabs) = 0;

	// ****************************************************************************
	//								ExtraTabsLoaded
	// 
	/// Tells the client that the extra tabs have been loaded
	/// 
	/// \param inHostPart  The properties host part (so you can find things by ID if you need to)
	/// 
	virtual void		MCCOMAPI	ExtraTabsLoaded(IMFPart* inHostPart) = 0;

	// ****************************************************************************
	//								UnLoadProperties
	// 
	/// Called when the client is removed from the properties so that it can release references it shouldn't keep
	/// 
	/// \param inPropertiesSplitBar  Pointer to the properties window split bar.  Use to store its position in the client's preferences.
	/// 
	virtual void		MCCOMAPI	UnLoadProperties(IMFSplitBarPart* inPropertiesSplitBar) = 0;

	// ****************************************************************************
	//								PreLoadProperties
	// 
	/// Called when the client is about to be put in the properties.  The client should set the splitbar to the position it prefers for it.
	/// 
	/// \param inPropertiesSplitBar  Pointer to the properties window split bar part.
	/// 
	virtual void		MCCOMAPI	PreLoadProperties(IMFSplitBarPart* inPropertiesSplitBar) = 0;

	/// Called during the validation of the property module (usually before drawing the UI)
	/// => this is the place where you should load panels invalidated during a data changed
	virtual void		MCCOMAPI	Validate() = 0;
};

/// \}

#endif

