// ControlImpl.h
// Default interface Implementations for controls

#ifndef __CONTROLIMPL_H
#define __CONTROLIMPL_H

#include "..\Inject\SinkImpl.h"

template< class cImpl, class ILayoutItf, const IID *pDispIID, const GUID *pLib >
class ATL_NO_VTABLE ILayoutImpl
: public IControlImpl< cImpl, ILayoutItf, pDispIID, pLib >,
public ILayerRenderImpl,
public ILayerSchema
{
public:
   ILayoutImpl()
      // Initialize in the static range
      : m_nNextControlID( 1000 )
   {
   }

   long m_nNextControlID;

   // Override this function for custom schema fun
   void onSchemaLoad( IView *, MSXML::IXMLDOMElementPtr & )
   {
   }

   long loadChildControl( IView *pView, const MSXML::IXMLDOMElementPtr &pChild )
   {
      _ASSERTE( pView != NULL );
      _ASSERTE( pChild.GetInterfacePtr() != NULL );

      long nAssigned;
      pView->LoadControl( static_cast< cImpl * >( this )->m_pSite, ++ m_nNextControlID, pChild, &nAssigned );

      return nAssigned;
   }

   long dispenseID()
   {
      return ++ m_nNextControlID;
   }

   CComPtr< IImageCache > m_pBackground;

   // ILayout Methods
   STDMETHOD(get_Background)( IImageCacheDisp **ppVal )
   {
      _ASSERTE( ppVal != NULL );

      if( m_pBackground.p == NULL )
         *ppVal = NULL;
      else
         m_pBackground->QueryInterface( ppVal );

      return S_OK;
   }

   STDMETHOD(putref_Background)( IImageCacheDisp *pCache )
   {
      if( m_pBackground.p )
         m_pBackground.Release();

      if( pCache != NULL )
         pCache->QueryInterface( &m_pBackground );

      static_cast< cImpl * >( this )->m_pSite->Invalidate();

      return S_OK;
   }

   // ILayerRender Methods
   STDMETHOD(Render)( ICanvas *pCanvas )
   {
      if( m_pBackground.p == NULL )
         // No background means no drawing
         return S_OK;

      // Tile the background into the clipping area
      ClipParams cp;
      pCanvas->GetClipParams( &cp );

      RECT rc = { cp.org.x, cp.org.y, cp.org.x + ( cp.window.right - cp.window.left ),
         cp.org.y + ( cp.window.bottom - cp.window.top ) };

      m_pBackground->PatBlt( pCanvas, &rc, &cp.org );

      return S_OK;
   }

   // ILayerSchema Methods
   STDMETHOD(SchemaLoad)(IView *pView, IUnknown *pXMLSchema )
   {
      MSXML::IXMLDOMElementPtr pElement = pXMLSchema;
      CComPtr< IPluginSite > pPluginSite;
      static_cast< cImpl * >( this )->m_pSite->get_PluginSite( &pPluginSite );

      HRESULT hRes = pPluginSite->LoadImageSchema( pXMLSchema, &m_pBackground );
      _ASSERTE( SUCCEEDED( hRes ) );

      static_cast< cImpl * >( this )->onSchemaLoad( pView, pElement );

      return S_OK;
   }
};

template< UINT nID, class cImpl >
class IScrollerEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_IScrollerEvents, &LIBID_DecalControls >
{
};

template< UINT nID, class cImpl >
class IListEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_IListEvents, &LIBID_DecalControls >
{
};

template< UINT nID, class cImpl >
class INotebookEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_INotebookEvents, &LIBID_DecalControls >
{
};

#define DISPID_BEGIN 10
#define DISPID_END 11

template< UINT nID, class cImpl >
class IEditEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_IEditEvents, &LIBID_DecalControls >
{
};

#define DISPID_DROPDOWN 12

template< UINT nID, class cImpl >
class IChoiceEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_IChoiceEvents, &LIBID_DecalControls >
{
};

template< UINT nID, class cImpl >
class ICheckboxEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_ICheckboxEvents, &LIBID_DecalControls >
{
};

template< UINT nID, class cImpl >
class ISliderEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_ISliderEvents, &LIBID_DecalControls >
{
};

#endif
