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

		BasicMCFCOMImplementations.cpp

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

		Author:	Ray Dream
		Date:	3/2/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		11/21/99	Ian			SelfMouseEntering() ...StillInside(), and ...Leaving(),
								call inherited IMFPart (if it exists).
		10/27/99	Yann		Added TBasicPart::BaseWindowBecameVisible
		10/13/99	Yann		Added support for IMFExPart::SetShown
		10/05/99	EricB		IShMouseAction can now be 'not constrained to the view' they apply to.
								To do so, you just need to override the method ConstrainedToView, and return false.
								Default (TBasicMouseAction) returns true, to keep the previous behavior.
		9/28/99		Thierry		removed GC from Hilite parameters
		9/23/99		EricB		DropCandidate::GetOrigin parameter reverted to void**
		09/12/99	Pierre		Merged BecameFirstResponder and ResignedFirstResponder
		9/8/99		Greg		Added OnNoDrag
		9/06/99		EricB		DropCandidate::GetOrigin parameter changed from void** to IMCUnknown**
		8/16/99		Ian			Added override of NeedsToPrepareMenus.
		8/1/99		Ian			Mouse moved API change.
		06/11/99	del			Added GetIndirectToolAction()
		6/1/99		Yann		Added more TBasicListPart methods (that Emil had marked as "to do")
		5/4/99		psq			removed AddRef in Track
		4/20/99		Greg		Added GetThisPartNoAddRef()
		4/5/99		Greg		Added SelfPrepareToDestroy in BasicPart
		3/23/99		Greg		DragDrop cleanup, DragDrop tool support in BasicPart,
								BasicPart::SelfDraw calls aggregated internal part
		3/3/99		Greg		Added GetValue and SetValue to BasicPart
		02/19/99	EricB		AddRef/Release in TBasicMouseAction::Track
		2/17/99		EricB		Changed 'nextAction' to 'this', in TBasicMouseAction::Track
		2/17/99		EricB		Added 'nextAction' as a return argument to IShMouseAction::Track
		2/16/99		Greg		Added TBasicPart::GetDropArea, TBasicDropArea and TBasicDropCandidate
		2/11/99		Joshua		Added IMFExPart::ParentChangedBounds
		1/13/99		Eml			Added IMFExPart::FinishRead
		12/15/98	Nba			added ReleaseIfNotNull_ in QueryInterfaces
		11/24/98	Joshua		Added SelfToolAction
		11/23/98	pbk			split from BasicCOM implementation

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

#include "ComSupportPublicAPIMainHeaders.h"

#include "COMUtilities.h"
#include "MCException.h"
#include "MCCountedPtrHelper.h"
#include "IMFExListPart.h"
#include "IShUtilities.h"
#include "IMFExListPart.h"
#include "IMFPart.h"
#include "IMFResponder.h"

//This line must be placed below #define INITGUID
#include "BasicMCFCOMImplementations.h"


//**************************************************************************************************
//  Implementation of TBasicPart
//**************************************************************************************************

TBasicPart::TBasicPart()
{
	fNeverCalledDestroy= true;
}

MCCOMErr TBasicPart::QueryInterface(const MCIID& riid, void** ppvObj)
{
	if (MCIsEqualIID(riid, IID_IMFExPart))
	{
		TMCCountedGetHelper<IMFExPart> result(ppvObj);
		result = this;
		return MC_S_OK;
	}
	else if (MCIsEqualIID(riid, IID_IMFExResponder))
	{
		TMCCountedGetHelper<IMFExResponder> result(ppvObj);
		result = this;
		return MC_S_OK;
	}
	return TBasicUnknown::QueryInterface(riid, ppvObj);
}

void TBasicPart::SelfActivate(boolean beActive)
{
}

void TBasicPart::SetShown(boolean inShown)
{
}

void TBasicPart::BaseWindowBecameVisible(boolean inShown)
{
}

boolean	TBasicPart::SelfMouseWheel(const TMCPoint& inWhere, const TMCModifiers& inModifiers, int16 inWheelDelta)
{
	return false;
}


boolean TBasicPart::SelfMouseMoved(const TMCPoint& inWhere, const TMCModifiers& inModifiers)
{
	return false;
}

void TBasicPart::SelfMouseEntering(const TMCPoint& inWhere, const TMCModifiers& inModifiers)
{
	if(GetThisPartNoAddRef())
	{
		GetThisPartNoAddRef()->SelfMouseEntering(inWhere, inModifiers);
	}
}

void TBasicPart::SelfMouseStillInside(const TMCPoint& inWhere, const TMCModifiers& inModifiers)
{
	if(GetThisPartNoAddRef())
	{
		GetThisPartNoAddRef()->SelfMouseStillInside(inWhere, inModifiers);
	}
}

void TBasicPart::SelfMouseLeaving(const TMCModifiers& inModifiers)
{
	if(GetThisPartNoAddRef())
	{
		GetThisPartNoAddRef()->SelfMouseLeaving(inModifiers);
	}
}

TMFEventResult TBasicPart::SelfMouseDown(const TMCPoint& inWhere, const TMCPlatformEvent& inEvent)
{
	return TMFEventResult();
}

boolean TBasicPart::SelfContextMouseDown(const TMCPoint& inWhere, const TMCPlatformEvent& inEvent)
{
	return false;
}

boolean TBasicPart::SelfMiddleMouseDown(const TMCPoint& inWhere, const TMCPlatformEvent& inEvent)
{
	return false;
}


void TBasicPart::SelfTrackDragAndDropEntering(const TMCPoint& inWhere, const TMFDragFlavors& inOfferedTypeList)
{
}

void TBasicPart::SelfTrackDragAndDropStillInside(const TMCPoint& inWhere, const TMFDragFlavors& inOfferedTypeList)
{
}

void TBasicPart::SelfTrackDragAndDropLeaving(const TMFDragFlavors& inOfferedTypeList)
{
}

MFCursorID	TBasicPart::GetCursorID(const TMCPoint& inWhere) const
{
	return 0;
}

void TBasicPart::SelfDraw(IMCGraphicContext* graphicContext, const TMCRect& inZone)
{
	TMCCountedPtr<IMFPart> thisPart;
	QueryInterface(IID_IMFPart, (void **)&thisPart);
	if (thisPart)
		thisPart->SelfDraw(graphicContext, *(TMCRect*)&inZone);
}

boolean	TBasicPart::Receive(int32 message, IMFResponder* source, void* data)
{
	return 0;
}

void TBasicPart::SelfPrepareToDestroy()
{
	fThisPart			= NULL;
	fNeverCalledDestroy	= false;
}

void TBasicPart::FinishRead()
{
}

boolean TBasicPart::ParentChangedBounds(const TMCRect& oldBounds,const TMCRect& newBounds,boolean inval)
{
	return false;
}

boolean TBasicPart::ChangedBounds(const TMCRect& oldBounds,const TMCRect& newBounds,boolean inval)
{
	return false;
}

boolean TBasicPart::SelfMenuAction(ActionNumber actionNumber)
{
	return false;
}

void TBasicPart::SelfPrepareMenus()
{
}

boolean MCCOMAPI TBasicPart::SelfKeyDown(TMCPlatformEvent* event)
{
	return false;
}

void MCCOMAPI TBasicPart::SelfKeyUp(TMCPlatformEvent* event)
{
}

boolean TBasicPart::SelfToolAction(int32 inOldTool, int32 inNewTool)
{
	return false;
}

void TBasicPart::GetDropArea(
						const TMCPoint&		inWhere,
						IMFDropCandidate&	inCandidate,
						IDType&				outAcceptedFlavor,
						IMFDropArea**		outDropArea,
						boolean&			outDrawDropCandidate)
{
	TMCCountedGetHelper<IMFDropArea> result(outDropArea);
}

boolean TBasicPart::GetValue(
						void* 				outValue, 
						MFPartValueType 	inValueType) const
{
	return false;
}

boolean TBasicPart::SetValueLowLevel(const void* inValue, MFPartValueType inValueType)
{
	return false;
}

boolean TBasicPart::GetToolDropCandidate(
						IMFDropCandidate**	outDropCandidate,
						int32				inToolID,
						IMFToolbarPart*		inToolbarPart)
{
	TMCCountedGetHelper<IMFDropCandidate> result(outDropCandidate);
	return false;
}

boolean	MCCOMAPI TBasicPart::GetIndirectToolAction(IShMouseAction** outAction, ActionNumber &outActionNumber, IMFResponder **outContext, IMFPart **outPart, const TMCPoint &inWhere, int32 inToolID, IMFToolbarPart *inToolbarPart)
{
	TMCCountedGetHelper<IShMouseAction> result0(outAction);
	TMCCountedGetHelper<IMFResponder> result1(outContext);
	TMCCountedGetHelper<IMFPart> result2(outPart);
	return false;
}

IMFPart* TBasicPart::GetThisPartNoAddRef() const
{
	if (!fThisPart && MCVerify(fNeverCalledDestroy))
	{
		const_cast<TBasicPart*>(this)->QueryInterface(IID_IMFPart, (void **)&fThisPart);
	}
	return fThisPart;
}

void MCCOMAPI  TBasicPart::BecameFirstResponder(boolean on)
{
	TMCCountedPtr<IMFResponder> thisResponder;
	QueryInterface(IID_IMFResponder, (void **)&thisResponder);
	if (thisResponder)
		thisResponder->BecameFirstResponder(on);
}


void TBasicPart::BroadcastUp(MessageID message, void* data)
{
	IMFPart* thisPart= GetThisPartNoAddRef();
	if (MCVerify(thisPart))
	{
		TMCCountedPtr<IMFResponder> thisResponder;
		thisPart->QueryInterface(IID_IMFResponder, (void**)&thisResponder);
		if (MCVerify(thisResponder))
		{
			thisResponder->BroadcastMessageUp(message, thisResponder, data);
		}
	}
}

//**************************************************************************************************
//  Implementation of TBasicListPart
//**************************************************************************************************

MCCOMErr TBasicListPart::QueryInterface(const MCIID& riid, void** ppvObj)
{
	if (MCIsEqualIID(riid, IID_IMFExListPart))
	{
		TMCCountedGetHelper<IMFExListPart> result(ppvObj);
		result = this;
		return MC_S_OK;
	}
	return TBasicUnknown::QueryInterface(riid, ppvObj);
}

void TBasicListPart::SelfDrawCell(IMCGraphicContext* graphicContext, const TMCRect& cellRect, int32 inCell, boolean isSelected)
{
}

void TBasicListPart::SelfHiliteCell(IMCGraphicContext* context, const TMCRect& cellRect, int32 inCell, boolean isSelected)
{
}

boolean TBasicListPart::SelfClick(const TMCPoint& mouse, int32 hitCell)
{
	return false;
}

void TBasicListPart::SelfDoubleClick(const TMCPoint& mouse, int32 hitCell)
{
}

void TBasicListPart::SelfDragDrop(const TMCRect& cellRect, int32 hitCell, const TMCPoint& m2)
{
}

void TBasicListPart::SelfDragCell(int32 fromCell, int32 toCell)
{
}


//**************************************************************************************************
//  Implementation of TBasicAction
//**************************************************************************************************

MCCOMErr TBasicAction::QueryInterface(const MCIID &riid, void** ppvObj)
{
	if (MCIsEqualIID(riid, IID_IShAction))
	{
		TMCCountedGetHelper<IShAction> result(ppvObj);
		result = this;
		return MC_S_OK;
	}
	return TBasicUnknown::QueryInterface(riid, ppvObj);
}


MCCOMErr TBasicAction::Do()
{
	return MC_E_NOTIMPL;
}

MCCOMErr TBasicAction::Undo()
{
	return MC_E_NOTIMPL;
}

MCCOMErr TBasicAction::Redo()
{
	return MC_E_NOTIMPL;
}

boolean  TBasicAction::WillCauseChange()
{
	return false;
}

boolean  TBasicAction::CanUndo()
{
	return false;
}

void TBasicAction::GetPartToRedraw(IMFPart** outPart,int32 stage)
{
	TMCCountedGetHelper<IMFPart> result(outPart);
}

MCCOMErr TBasicAction::GetName(TMCString& name)
{
	return MC_E_NOTIMPL;
}

boolean TBasicAction::NeedsToPrepareMenus(void)
{
	return CanUndo();		//if the action is undoable, the undo menu needs to be rebuilt!
}


//**************************************************************************************************
//  Implementation of TBasicMouseAction
//**************************************************************************************************

MCCOMErr TBasicMouseAction::QueryInterface(const MCIID &riid, void** ppvObj)
{
	if (MCIsEqualIID(riid, IID_IShMouseAction))
	{
		TMCCountedGetHelper<IShMouseAction> result(ppvObj);
		result = this;
		return MC_S_OK;
	}
	return TBasicUnknown::QueryInterface(riid, ppvObj);
}


MCCOMErr TBasicMouseAction::Do()
{
	return MC_E_NOTIMPL;
}

MCCOMErr TBasicMouseAction::Undo()
{
	return MC_E_NOTIMPL;
}

MCCOMErr TBasicMouseAction::Redo()
{
	return MC_E_NOTIMPL;
}

boolean  TBasicMouseAction::WillCauseChange()
{
	return false;
}

boolean  TBasicMouseAction::CanUndo()
{
	return false;
}

MCCOMErr TBasicMouseAction::GetName(TMCString& name)
{
	return MC_E_NOTIMPL;
}

void TBasicMouseAction::Track(IMCGraphicContext* gc, int16 stage, TMCPoint& first, TMCPoint &prev, TMCPoint &cur,boolean moved, IShMouseAction**	nextAction)
{
	TMCCountedGetHelper<IShMouseAction> result(nextAction);
	result = this;
}

void TBasicMouseAction::TrackEx(IMCGraphicContext* gc, int16 stage, const TMFTabletMouseSample& first, const TMFTabletMouseSample& prev, const TMFTabletMouseSample& cur, boolean moved, IShMouseAction** nextAction)
{
	TMCCountedGetHelper<IShMouseAction> result(nextAction);
	result = this;
}

MCCOMErr TBasicMouseAction::Feedback(IMCGraphicContext* gc, int16 stage,const TMCPoint& first,const TMCPoint &prev,const TMCPoint &cur,boolean moved,boolean show)
{
	return MC_E_NOTIMPL;
}

void TBasicMouseAction::GetPartToRedraw(IMFPart** outPart,int32 stage)
{
	TMCCountedGetHelper<IMFPart> result(outPart);
}


MCCOMErr TBasicMouseAction::Constrain(IMCGraphicContext* gc, int16 stage,const TMCPoint& first,const TMCPoint &prev,TMCPoint &cur,boolean moved) 
{
	return MC_E_NOTIMPL;
}

boolean TBasicMouseAction::NeedsToPrepareMenus(void)
{
	return CanUndo(); //if the action is undoable, the undo menu needs to be rebuilt!
}

boolean TBasicMouseAction::ConstrainedToView(void)
{
	return true;
}

boolean TBasicMouseAction::IsPerpetualMouseAction(void)
{
	return false;
}

boolean TBasicMouseAction::ShouldHideCursor(void)
{
	return false;
}

boolean TBasicMouseAction::ShouldAutoScroll(void)
{
	return true;
}

boolean TBasicMouseAction::KeepTracking()
{
	return true;	
}

boolean TBasicMouseAction::WantsTabletTracking()
{
	return false;
}


//**************************************************************************************************
//  Implementation of TSimpleMouseAction
//**************************************************************************************************

void TSimpleMouseAction::PostSimpleMouseAction(const TMCPoint& inWhere, TBasicPart* trackingPart)
{
	if (MCVerify(trackingPart))
	{
		TMCCountedPtr<IShMouseAction> action(new TSimpleMouseAction(trackingPart));
		
		TMCCountedPtr<IMFResponder> context;
		trackingPart->QueryInterface(IID_IMFResponder, (void **)&context);
		
		gActionManager->PostMouseAction(action, 1, context, trackingPart->GetThisPartNoAddRef(), inWhere);
	}
}

TSimpleMouseAction::TSimpleMouseAction(TBasicPart* trackingPart)
{
	fTrackingPart= trackingPart;
	MCAssert(fTrackingPart);
}

TSimpleMouseAction::~TSimpleMouseAction()
{
}

void TSimpleMouseAction::Track(IMCGraphicContext* gc, int16 stage, TMCPoint& first, TMCPoint &prev, TMCPoint &cur,boolean moved, IShMouseAction**	nextAction)
{	
	if (moved)
	{
		ThrowIfNil(fTrackingPart);
		fTrackingPart->TrackMouse(stage, first, prev, cur);
	}
	TBasicMouseAction::Track(gc,stage,first,prev,cur,moved,nextAction);
}




//**************************************************************************************************
//  Implementation of TBasicDropArea
//**************************************************************************************************

TBasicDropArea::TBasicDropArea()
{
	fPart = NULL;
}
		
MCCOMErr TBasicDropArea::QueryInterface(const MCIID &riid, void** ppvObj)
{
	if (MCIsEqualIID(riid, IID_IMFExDropArea))
	{
		TMCCountedGetHelper<IMFExDropArea> result(ppvObj);
		result = this;
		return MC_S_OK;
	}
	return TBasicUnknown::QueryInterface(riid, ppvObj);	
}

boolean TBasicDropArea::DragIsAcceptable(
							TMFDragFlavors&		/*inOfferedFlavors*/,
							IDType&				/*inAcceptedFlavor*/,
							const TMCPoint&		/*inWhere*/)
{
	return false;
}

void TBasicDropArea::Hilite(
						boolean 			/*inIsHilited*/)
{
}

boolean	TBasicDropArea::IsEqualTo(
							IMFExDropArea* 		/*inArea*/)
{
	return true;
}

void TBasicDropArea::ReceiveDrop(
						IMFDropCandidate*	/*dropCandidate*/,
						IDType&				/*acceptedType*/,
						MFDragDropType		/*moveOrCopy*/,
						const TMCPoint&		/*mousePos*/)
{
}
		
void TBasicDropArea::GetPart(
						IMFPart** 			outPart)
{
	TMCCountedGetHelper<IMFPart> result(outPart);
	result = fPart;
}


//**************************************************************************************************
//  Implementation of TBasicDropCandidate
//**************************************************************************************************

TBasicDropCandidate::TBasicDropCandidate()
{
}

MCCOMErr TBasicDropCandidate::QueryInterface(const MCIID &riid, void** ppvObj)
{
	if (MCIsEqualIID(riid, IID_IMFExDropCandidate))
	{
		TMCCountedGetHelper<IMFExDropCandidate> result(ppvObj);
		result = this;
		return MC_S_OK;
	}
	return TBasicPart::QueryInterface(riid, ppvObj);	
}


MCCOMErr TBasicDropCandidate::GetData(
							IDType 			/*inFlavor*/, 
							MFDragDropType 	/*inMoveOrCopy*/,
							void**			/*outData*/)
{
	return MC_S_OK;
}

void TBasicDropCandidate::GetOrigin(
							void**	/*outData*/)
{
}

void TBasicDropCandidate::GetOfferedFlavors(TMFDragFlavors& outFlavors)
{
	outFlavors = fFlavors;
}

void TBasicDropCandidate::PrepareToDrag()
{
}
	
void TBasicDropCandidate::FinishedDrag(boolean /*inSuccessful*/)
{
}

void TBasicDropCandidate::OnNoDrag()
{
}

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