// Scroller.h : Declaration of the cScroller

#ifndef __SCROLLER_H_
#define __SCROLLER_H_

#include "resource.h"       // main symbols
#include "SinkImpl.h"
#include "DecalControlsCP.h"

#define PAGER_CLIENT 1
#define BUTTON_LEFT 2
#define BUTTON_RIGHT 3
#define BUTTON_UP 4
#define BUTTON_DOWN 5

/////////////////////////////////////////////////////////////////////////////
// cScroller
class ATL_NO_VTABLE cScroller : 
	public CComObjectRootEx<CComMultiThreadModel>,
	public CComCoClass<cScroller, &CLSID_Scroller>,
	public IConnectionPointContainerImpl<cScroller>,
	public ILayerImpl< cScroller >,
	public ILayerRenderImpl,
   public ILayerMouseImpl,
   public IProvideClassInfo2Impl< &CLSID_Scroller, &DIID_IScrollerEvents, &LIBID_DecalControls >,
	public IControlImpl< cScroller, IScroller, &IID_IControl, &LIBID_DecalPlugins >,
	public ICommandEventsImpl< BUTTON_LEFT, cScroller >,
	public ICommandEventsImpl< BUTTON_RIGHT, cScroller >,
	public ICommandEventsImpl< BUTTON_UP, cScroller >,
	public ICommandEventsImpl< BUTTON_DOWN, cScroller >,
	public IPagerEventsImpl< PAGER_CLIENT, cScroller >,
   public ILayerSchema,
   public CProxyIScrollerEvents< cScroller >
{
public:
	cScroller()
      : m_nCurrentCommand( -1 )
	{
	}

	CComPtr< IPager > m_pPager;

   CComPtr< IImageCache > m_pHScrollBack;
   CComPtr< IImageCache > m_pVScrollBack;

   SIZE m_szArea;
   SIZE m_szIncrement;
   SIZE m_szPage;
   POINT m_ptThumb;

   // Members for live dragging of the thumbs
   long m_nCurrentCommand,
      m_nScreenStart,
      m_nThumbStart;
   POINT m_ptMouseLast;

   VARIANT_BOOL m_bHScroll,
      m_bVScroll;

   void onCreate();
   void onDestroy();

   // Helper functions
   long hitTest( MouseState *pMS );
   void constrainOffset( LPPOINT ppt );

DECLARE_REGISTRY_RESOURCEID(IDR_SCROLLER)
DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(cScroller)
	COM_INTERFACE_ENTRY(ILayerRender)
   COM_INTERFACE_ENTRY(ILayerMouse)
   COM_INTERFACE_ENTRY(ILayerSchema)
	COM_INTERFACE_ENTRY(IScroller)
   COM_INTERFACE_ENTRY(IControl)
   COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(ILayer)
   COM_INTERFACE_ENTRY(ILayerSchema)
   COM_INTERFACE_ENTRY(IProvideClassInfo)
   COM_INTERFACE_ENTRY(IProvideClassInfo2)
	COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(cScroller)
CONNECTION_POINT_ENTRY(DIID_IScrollerEvents)
END_CONNECTION_POINT_MAP()

BEGIN_SINK_MAP(cScroller)
   SINK_ENTRY_EX( PAGER_CLIENT, DIID_IPagerEvents, DISPID_CHANGE, onClientChange )
   SINK_ENTRY_EX( PAGER_CLIENT, DIID_IPagerEvents, DISPID_GETNEXTPOSITION, onClientGetNextPosition )
   SINK_ENTRY_EX( BUTTON_UP, DIID_ICommandEvents, DISPID_HIT, onButtonHit )
   SINK_ENTRY_EX( BUTTON_UP, DIID_ICommandEvents, DISPID_UNHIT, onButtonUnhit )
   SINK_ENTRY_EX( BUTTON_DOWN, DIID_ICommandEvents, DISPID_HIT, onButtonHit )
   SINK_ENTRY_EX( BUTTON_DOWN, DIID_ICommandEvents, DISPID_UNHIT, onButtonUnhit )
   SINK_ENTRY_EX( BUTTON_LEFT, DIID_ICommandEvents, DISPID_HIT, onButtonHit )
   SINK_ENTRY_EX( BUTTON_LEFT, DIID_ICommandEvents, DISPID_UNHIT, onButtonUnhit )
   SINK_ENTRY_EX( BUTTON_RIGHT, DIID_ICommandEvents, DISPID_HIT, onButtonHit )
   SINK_ENTRY_EX( BUTTON_RIGHT, DIID_ICommandEvents, DISPID_UNHIT, onButtonUnhit )
END_SINK_MAP()

public:
	STDMETHOD(ResetScroller)();
	// IScroller Methods
	STDMETHOD(get_Viewport)(/*[out, retval]*/ LPSIZE pVal);
	STDMETHOD(get_Area)(/*[out, retval]*/ LPSIZE pVal);
	STDMETHOD(put_Area)(/*[in]*/ LPSIZE newVal);
	STDMETHOD(get_HorizontalEnabled)(/*[out, retval]*/ VARIANT_BOOL *pVal);
	STDMETHOD(put_HorizontalEnabled)(/*[in]*/ VARIANT_BOOL newVal);
	STDMETHOD(get_VerticalEnabled)(/*[out, retval]*/ VARIANT_BOOL *pVal);
	STDMETHOD(put_VerticalEnabled)(/*[in]*/ VARIANT_BOOL newVal);
	STDMETHOD(CreateClient)(ILayer *pChild);
	STDMETHOD(get_Offset)(/*[out, retval]*/ LPPOINT pVal);
	STDMETHOD(put_Offset)(/*[in]*/ LPPOINT newVal);
	STDMETHOD(ScrollTo)(LPPOINT ptOffset);
	STDMETHOD(get_Increments)(/*[out, retval]*/ LPSIZE pVal);
	STDMETHOD(put_Increments)(/*[in]*/ LPSIZE newVal);

	// ILayerRender Methods
   STDMETHOD(Render)(ICanvas *pCanvas);
	STDMETHOD(Reformat)();

	// ICommandEvents Methods
   void __stdcall onButtonHit( long nID );
   void __stdcall onButtonUnhit( long nID );

	// IPagerEvents Methods
   void __stdcall onClientChange( long nID, long nCommand, long nX, long nY );
   VARIANT_BOOL __stdcall onClientGetNextPosition( long nID, long nCommand, long *pnX, long *pnY );

   // ILayerMouse Methods
   STDMETHOD(MouseDown)(MouseState *pMS);
   STDMETHOD(MouseUp)(MouseState *pMS);
   STDMETHOD(MouseMove)(MouseState *pMS);

   // ILayerSchema Methods
   STDMETHOD(SchemaLoad)(IView *pView, IUnknown *pXMLElement);
};

#endif //__SCROLLER_H_
