// SpringCtl.h : Declaration of the CSpringCtl

#ifndef __SPRINGCTL_H_
#define __SPRINGCTL_H_

#include <math.h>
#include "resource.h"       // main symbols
#include <atlctl.h>
#include "SpringCP.h"


//
// This ActiveX Control hosts a toy-program showing a spring embedder algorithm, 
// a heuristic approach to graph drawing based on a physical system.
// Here is simple implemenatation, restricted to 2D. 
// The objective is to show the alogrithm at work, not the results, 
// and to have fun watching the algorithm imitating the mechanical process. 
// 
// Moving the mouse over the control activates the step-by-step iteration:
// so we have a message handler OnMouseMove().
// Mouse click restarts the algorithm - the corresponding handler is OnLButtonDown().
// 



class BRIDGE;

/////////////////////////////////////////////////////////////////////////////
// CSpringCtl
class ATL_NO_VTABLE CSpringCtl :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CStockPropImpl<CSpringCtl, ISpringCtl, &IID_ISpringCtl, &LIBID_SPRINGLib>,
    public CComControl<CSpringCtl>,
    public IPersistStreamInitImpl<CSpringCtl>,
    public IOleControlImpl<CSpringCtl>,
    public IOleObjectImpl<CSpringCtl>,
    public IOleInPlaceActiveObjectImpl<CSpringCtl>,
    public IViewObjectExImpl<CSpringCtl>,
    public IOleInPlaceObjectWindowlessImpl<CSpringCtl>,
    public ISupportErrorInfo,
    public IConnectionPointContainerImpl<CSpringCtl>,
    public IPersistStorageImpl<CSpringCtl>,
    public ISpecifyPropertyPagesImpl<CSpringCtl>,
    public IQuickActivateImpl<CSpringCtl>,
    public IDataObjectImpl<CSpringCtl>,
    public IProvideClassInfo2Impl<&CLSID_SpringCtl, &DIID__ISpringCtlEvents, &LIBID_SPRINGLib>,
    public IPropertyNotifySinkCP<CSpringCtl>,
    public CComCoClass<CSpringCtl, &CLSID_SpringCtl>,
    public CProxy_ISpringCtlEvents< CSpringCtl >,
    public IObjectSafetyImpl<CSpringCtl, INTERFACESAFE_FOR_UNTRUSTED_CALLER>
{
public:
    CSpringCtl();

DECLARE_REGISTRY_RESOURCEID(IDR_SPRINGCTL)

BEGIN_COM_MAP(CSpringCtl)
    COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
    COM_INTERFACE_ENTRY(ISpringCtl)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IViewObjectEx)
    COM_INTERFACE_ENTRY(IViewObject2)
    COM_INTERFACE_ENTRY(IViewObject)
    COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
    COM_INTERFACE_ENTRY(IOleInPlaceObject)
    COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
    COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
    COM_INTERFACE_ENTRY(IOleControl)
    COM_INTERFACE_ENTRY(IOleObject)
    COM_INTERFACE_ENTRY(IPersistStreamInit)
    COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
    COM_INTERFACE_ENTRY(IConnectionPointContainer)
    COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
    COM_INTERFACE_ENTRY(IQuickActivate)
    COM_INTERFACE_ENTRY(IPersistStorage)
    COM_INTERFACE_ENTRY(IDataObject)
    COM_INTERFACE_ENTRY(IProvideClassInfo)
    COM_INTERFACE_ENTRY(IProvideClassInfo2)
    COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()

BEGIN_PROP_MAP(CSpringCtl)
    PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
    PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
    PROP_ENTRY("FillColor", DISPID_FILLCOLOR, CLSID_StockColorPage)
//  PROP_ENTRY("Sides", 1, CLSID_SpringProp)
    // Example entries
    // PROP_ENTRY("Property Description", dispid, clsid)
    // PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()

BEGIN_CONNECTION_POINT_MAP(CSpringCtl)
    CONNECTION_POINT_ENTRY(DIID__ISpringCtlEvents)
    CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
END_CONNECTION_POINT_MAP()

BEGIN_MSG_MAP(CSpringCtl)
    MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
    MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
    CHAIN_MSG_MAP(CComControl<CSpringCtl>)
    DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
// Handler prototypes:
//  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);



// ISupportsErrorInfo
    STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
    {
        static const IID* arr[] =
        {
            &IID_ISpringCtl,
        };
        for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
        {
            if (InlineIsEqualGUID(*arr[i], riid))
                return S_OK;
        }
        return S_FALSE;
    }

// IViewObjectEx
    DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

// ISpringCtl
public:
    STDMETHOD(get_Width)(/*[out, retval]*/ short *pVal);
    STDMETHOD(put_Width)(/*[in]*/ short newVal);
    STDMETHOD(get_Height)(/*[out, retval]*/ short *pVal);
    STDMETHOD(put_Height)(/*[in]*/ short newVal);


    HRESULT OnDraw(ATL_DRAWINFO& di);

    LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/);
    LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/);

    short width;
    short height;
    BRIDGE *graph;
};

#endif //__SPRINGCTL_H_
