// LayerSite.h : Declaration of the cLayerSite

#ifndef __LAYERSITE_H
#define __LAYERSITE_H

#include "resource.h"       // main symbols

/////////////////////////////////////////////////////////////////////////////
// cBarSite
class ATL_NO_VTABLE cLayerSite : 
	public CComObjectRootEx<CComMultiThreadModel>,
	public ILayerSite
{
public:
   typedef std::vector< cLayerSite * > cChildList;
   cChildList m_children;

   cLayerSite *m_pParent;

   CComPtr< ICanvas > m_pBuffer;

   DWORD m_dwSinkCaps;
   CComPtr< ILayer > m_pSink;

   LayerParams m_params;

   struct cTimer
   {
      long m_nLastTimeout,
         m_nID,
         m_nInterval, 
         m_nRepetitions;
   };

   long m_Alpha;

   typedef std::list< cTimer > cTimerList;
   cTimerList m_timers;

	cLayerSite();
   ~cLayerSite();

   // Child notification of destruction, remove the child
   // from the list.
   void removeChild( cLayerSite *pChild );

   // Scan our callback for capabilities - also perform some internal
   // initialization
   void create( LayerParams *pParams, cLayerSite *pParent, ILayer *pSink );
   void destroy();

   // Rendering operations
   void format();
   void formatLayer();

   void prerender();
   void render( ICanvas *pPrimary );
   void renderBuffer( ICanvas *pCanvas, bool bForceDraw );

   // Force a reformat for all layers - this usually occurs only
   // on a video-mode change
   void reformat();

   void moveChildToFront(long nIndex);

   // Mouse operations
   cLayerSite *hitTestUnclipped( POINTS pt, ICanvas *pCanvas );
   cLayerSite *hitTestClipped( POINTS pt, LPPOINT pptHit, ICanvas *pCanvas );
   cLayerSite *hitTest( POINTS pt, LPPOINT pptHit, ICanvas *pCanvas );
   void clipCanvas( ICanvas *pCanvas );
   bool isClippedChild( cLayerSite *pChild );
   bool isChild( cLayerSite *pChild );
   cLayerSite *getCommonClippedParent( cLayerSite *pOther );

   void sendMouseEnter( cLayerSite *pCommonParent, MouseState *pMS );
   void sendMouseExit( cLayerSite *pCommonParent, MouseState *pMS );
   void sendMouseMove( MouseState *pMS );
   void sendMouseDown( MouseState *pMS );
   void sendMouseUp( MouseState *pMS );
   void sendMouseDblClk( MouseState *pMS );
   void sendMouseEvent( long nMsg, long wParam, long lParam );

   void sendKeyboardEndCapture( VARIANT_BOOL bCancel );
   void sendKeyboardChar( KeyState *pKS );
   void sendKeyboardEvent( long nMsg, long wParam, long lParam );

   bool sendPopupCancel( MouseState *pMS );

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(cLayerSite)
	COM_INTERFACE_ENTRY(ILayerSite)
END_COM_MAP()

// ILayerSite
public:
	STDMETHOD(CreateChild)(LayerParams *params, ILayer *pSink);

	STDMETHOD(get_Position)(/*[out, retval]*/ RECT *pVal);
	STDMETHOD(put_Position)(/*[in]*/ RECT *newVal);
	STDMETHOD(get_ScreenPosition)(/*[out, retval]*/ RECT *pVal);

	STDMETHOD(Reformat)();
	STDMETHOD(Destroy)();
	STDMETHOD(Invalidate)();
	STDMETHOD(get_Transparent)(/*[out, retval]*/ VARIANT_BOOL *pVal);
	STDMETHOD(put_Transparent)(/*[in]*/ VARIANT_BOOL newVal);

	STDMETHOD(get_PluginSite)(IPluginSite **ppSite);
	STDMETHOD(GetSink)(REFIID iid, void **ppvItf);
	STDMETHOD(GetParentSink)(REFIID iid, /*[iid_is(iid)]*/ void **ppvItf);
	STDMETHOD(get_Child)(long nIndex, /*[defaultvalue(ePositionByIndex)]*/ ePositionType posType, /*[out, retval]*/ ILayerSite* *pVal);
	STDMETHOD(get_ChildCount)(/*[out, retval]*/ long *pVal);
	STDMETHOD(get_ID)(/*[out, retval]*/ long *pVal);
	STDMETHOD(IsChild)(ILayerSite *pSite, /*[optional, defaultvalue(VARIANT_FALSE)]*/ VARIANT_BOOL bTestUnclipped, /*[out, retval]*/ VARIANT_BOOL *pbIsChild);
	STDMETHOD(moveToFront)();

	STDMETHOD(CaptureKeyboard)();
	STDMETHOD(put_Popup)(/*[in]*/ VARIANT_BOOL newVal);
	STDMETHOD(StartTimer)(long nID, long nInterval);
	STDMETHOD(EndTimer)(long nID);

	STDMETHOD(put_Alpha)(long Alpha);
};

#endif //__LAYERSITE_H