// SinkImpl.h
// Declaration of interface helpers that provide default empty implementations
// for all of the sinks defined in the IDL file.
// This can help reduce the number of functions you have to write,
// to use, derived from the *Impl class instead of the interface directly then
// implement the functions you care about.

// These function are guaranteed never to do anything at all useful,
// so never call them. If you implement all the functions in the interface
// there is no reason to use these classes.

#ifndef __SINKIMPL_H
#define __SINKIMPL_H

#include "PluginImpl.h"

class ATL_NO_VTABLE ILayerRenderImpl : public ILayerRender
{
public:
   STDMETHOD(PreRender)();
   STDMETHOD(Render)( ICanvas *pCanvas );
   STDMETHOD(Reformat)();
   STDMETHOD(AdjustRenderArea)( ICanvas *pCanvas, VARIANT_BOOL *pbDrawChildren );
   STDMETHOD(HitTest)(LPPOINT pt, VARIANT_BOOL *pbHit);
};

template< class cImpl >
class ATL_NO_VTABLE ILayerImpl : public ILayer
{
public:
   // Override these methods
   CComPtr< ILayerSite > m_pSite;

   void onCreate()
   {
      // Override this function to initialize the control
   }

   void onDestroy()
   {
      // Override this function to release all stored objects
   }

   STDMETHOD(LayerCreate)(ILayerSite *pSite)
   {
      _ASSERTE( m_pSite.p == NULL );
      _ASSERTE( pSite != NULL );

      m_pSite = pSite;

      static_cast< cImpl * >( this )->onCreate();

      return S_OK;
   }

   STDMETHOD(LayerDestroy)()
   {
      _ASSERTE( m_pSite.p != NULL );

	  long nID;
      m_pSite->get_ID( &nID );

      static_cast< cImpl * >( this )->Fire_Destroy( nID );
      static_cast< cImpl * >( this )->onDestroy();

      m_pSite.Release();

      return S_OK;
   }
 
   STDMETHOD(put_Position)(RECT *newVal)
   {
	   return m_pSite->put_Position(newVal);
   }

   STDMETHOD(get_Position)(RECT *pVal)
   {
	   return m_pSite->get_Position(pVal);
   }

   STDMETHOD(Invalidate)()
   {
	   return m_pSite->Invalidate();
   }
};

class ATL_NO_VTABLE ILayerMouseImpl : public ILayerMouse
{
public:
	STDMETHOD(MouseEnter)(struct MouseState *pMouse);
	STDMETHOD(MouseExit)(struct MouseState *pMouse);
	STDMETHOD(MouseDown)(struct MouseState *pMouse);
	STDMETHOD(MouseUp)(struct MouseState *pMouse);
   STDMETHOD(MouseMove)(struct MouseState *pMouse);
   STDMETHOD(MouseDblClk)(struct MouseState *pMouse);
   STDMETHOD(MouseEvent)(long nMsg, long wParam, long lParam);
};

// This class implements the code IControl functions, to use this implementation,
// derive your control interface from IControl and pass your derived interface as
// IControlItf

// In your interface map, makes sure both IControl and your control interface
// are included.
template< class cImpl, class IControlItf, const IID *pDispItf, const GUID *pbLib >
class ATL_NO_VTABLE IControlImpl
: public IDispatchImpl< IControlItf, pDispItf, pbLib >
{
public:
   // Override this function if you care about child destruction
   void onChildDestroy( long nID )
   {
   }

   STDMETHOD(DestroyChild)(long nIndex, /*[defaultvalue(ePositionByIndex)]*/ enum ePositionType posType)
   {
      CComPtr< ILayerSite > pChildSite;
      HRESULT hRes = static_cast< cImpl * >( this )->m_pSite->get_Child( nIndex, posType, &pChildSite );
      if( !SUCCEEDED( hRes ) )
         return hRes;

      long nID;
      pChildSite->get_ID( &nID );

      // Do destroy preprocessing
      static_cast< cImpl * >( this )->onChildDestroy( nID );

      // Kill the child and return
      return pChildSite->Destroy();
   }

   STDMETHOD(get_ID)(/*[out, retval]*/ long *pnID )
   {
      return static_cast< cImpl * >( this )->m_pSite->get_ID( pnID );
   }

   STDMETHOD(get_ChildCount)(/*[out, retval]*/ long *pnChildCount )
   {
      return static_cast< cImpl * >( this )->m_pSite->get_ChildCount( pnChildCount );
   }

   STDMETHOD(get_Child)(long nIndex, /*[optional, defaultvalue(ePositionByIndex)]*/ ePositionType ePosType, /*[out, retval]*/ IControl **ppChild )
   {
      CComPtr< ILayerSite > pChildSite;
      HRESULT hRes = static_cast< cImpl * >( this )->m_pSite->get_Child( nIndex, ePosType, &pChildSite );
      if( FAILED( hRes ) )
         return hRes;

      return pChildSite->GetSink( IID_IControl, reinterpret_cast< void ** >( ppChild ) );
   }
   
   STDMETHOD(put_Position)(RECT *newVal)
   {
	   return static_cast< cImpl * >( this )->m_pSite->put_Position(newVal);
   }

   STDMETHOD(get_Position)(RECT *pVal)
   {
	   return static_cast< cImpl * >( this )->m_pSite->get_Position(pVal);
   }

};

// Derive from this class if your layer does not use an IControlEvents
// derived source interface. This is mainly intereded for internal framework
// classes.
class cNoEventsImpl
{
public:
   HRESULT Fire_Destroy( long )
   {
      return E_NOTIMPL;
   }
};

#endif
