// Panel.cpp : Implementation of cPanel
#include "stdafx.h"
#include "Inject.h"
#include "Panel.h"
#include "Manager.h"
/////////////////////////////////////////////////////////////////////////////
// cPanel

enum ePanelChildren
{
	eViewFirst = 1000
};

cPanel::cPanel()
: m_nActiveView( -1 ),
m_bDragging( false ),
m_bSizingXL( false ),
m_bSizingXR( false ),
m_bSizingYT( false ),
m_bSizingYB( false ),
m_bTransparent( false ),
m_pcView( NULL ),
m_Alpha( 255 )
{
}

void cPanel::hideView()
{
	m_pSite->Invalidate();

	if( m_nActiveView == -1 )
		// No active view currently
		return;

	CComPtr< ILayerSite > pActive;
	m_pSite->get_Child( m_nActiveView, ePositionByID, &pActive );

	static RECT rcHide = { 0, 0, 0, 0 };
	pActive->put_Position( &rcHide );

	if( m_pSink.p != NULL )
		m_pSink->PanelDeactivate( m_nActiveView );

	m_nActiveView = -1;
}

void cPanel::onCreate()
{
	CComPtr< IPluginSite > pPlugin;
	m_pSite->get_PluginSite( &pPlugin );

	pPlugin->LoadBitmapPortal( 0x0600126F, &m_pBackground );
	pPlugin->LoadBitmapPortal( 0x06001277, &m_pBorder );
	BSTR bstrFontName;
	pPlugin->get_FontName(&bstrFontName);
	pPlugin->CreateFont( bstrFontName /*_bstr_t( _T( "Times New Roman" ) )*/, 15, eFontBold, &m_pTitle );

	// Create the Button
	CComPtr< IButton > pRollup;

	HRESULT hRes = ::CoCreateInstance( CLSID_Button, NULL, CLSCTX_INPROC_SERVER, IID_IButton,
		reinterpret_cast< void ** >( &pRollup ) );

	_ASSERTE( SUCCEEDED( hRes ) );

	CComPtr< ILayer > pBtnLayer;
	pRollup->QueryInterface( &pBtnLayer );

	LayerParams lp = { 1, { 180 - 16, 0, 180, 16 }, eRenderClipped };
	m_pSite->CreateChild( &lp, pBtnLayer );

	pRollup->put_Matte( RGB( 0, 0, 0 ) );
	pRollup->SetImages( 0, 0x0600113C, 0x0600113B );
	ICommandEventsImpl< BUTTON_CLOSE, cPanel >::advise( pRollup );

	// Create the Increment Button
	hRes = ::CoCreateInstance( CLSID_Button, NULL, CLSCTX_INPROC_SERVER, IID_IButton,
		reinterpret_cast< void ** >( &m_pButtonInc ) );

	_ASSERTE( SUCCEEDED( hRes ) );

	CComPtr< ILayer > pBtnIncLayer;
	m_pButtonInc->QueryInterface( &pBtnIncLayer );

	LayerParams lpInc = { 2, { 180 - 32, 0, 180 - 32 + 16, 16 }, eRenderClipped };
	m_pSite->CreateChild( &lpInc, pBtnIncLayer );

	m_pButtonInc->put_Matte( RGB( 0, 0, 0 ) );
	m_pButtonInc->SetImages( 0, 0x06001298, 0x06001299 );

	ICommandEventsImpl< BUTTON_INC, cPanel >::advise( m_pButtonInc );

	// Create the Decrement Button
	hRes = ::CoCreateInstance( CLSID_Button, NULL, CLSCTX_INPROC_SERVER, IID_IButton,
		reinterpret_cast< void ** >( &m_pButtonDec ) );

	_ASSERTE( SUCCEEDED( hRes ) );

	CComPtr< ILayer > pBtnDecLayer;
	m_pButtonDec->QueryInterface( &pBtnDecLayer );

	LayerParams lpDec = { 3, { 180 - 48, 0, 180 - 48 + 16, 16 }, eRenderClipped };
	m_pSite->CreateChild( &lpDec, pBtnDecLayer );

	m_pButtonDec->put_Matte( RGB( 0, 0, 0 ) );
	m_pButtonDec->SetImages( 0, 0x06001295, 0x06001296 );

	ICommandEventsImpl< BUTTON_DEC, cPanel >::advise( m_pButtonDec );

	// Set this layer not transparent to be transparent
	m_pSite->put_Transparent( VARIANT_FALSE );

	RegKey key;
	key.Create( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\Decal" ) );

	if(key.QueryDWORDValue("ViewAlpha", m_Alpha) != ERROR_SUCCESS)
		m_Alpha = 255;
}

void cPanel::onDestroy()
{
	m_pBorder.Release();
	m_pBackground.Release();
	m_pTitle.Release();
	m_pButtonInc.Release();
	m_pButtonDec.Release();
}

STDMETHODIMP cPanel::Render( ICanvas *pCanvas )
{
	RECT rc;
	m_pSite->get_Position( &rc );

	SIZE szBorder;
	m_pBorder->get_Size( &szBorder );

	// Draw the background
	RECT rc_pat = { 0, 0, rc.right - rc.left, rc.bottom - rc.top };
	static POINT pt_pat = { 0, 0 };

	if( ! m_bTransparent )
		m_pBackground->PatBlt( pCanvas, &rc_pat, &pt_pat );

	// Draw the borders
	RECT rc_border_top = { 0, 0, rc.right - rc.left, szBorder.cy },
		rc_border_bottom = { 0, rc.bottom - rc.top - szBorder.cy, 
			rc.right - rc.left, rc.bottom - rc.top };

	pCanvas->Fill( &rc_border_top, RGB( 0, 0, 0 ) );
	m_pBorder->PatBlt( pCanvas, &rc_border_top, &pt_pat );
	pCanvas->Fill( &rc_border_bottom, RGB( 0, 0, 0 ) );
	m_pBorder->PatBlt( pCanvas, &rc_border_bottom, &pt_pat );

	// Draw the title text
	if( _bstr_t(m_pVP->label).length() > 0 )
	{
		POINT ptText = { 24, szBorder.cy + 5 };
		m_pTitle->DrawText( &ptText, m_pVP->label, 0, pCanvas );
	}

	if( m_pVP->icon != 0 )
	{
		CComPtr< IPluginSite > pPlugin;
		m_pSite->get_PluginSite( &pPlugin );

		CComPtr< IIconCache > pIconCache;
		static SIZE szIcon = { 16, 16 };
		pPlugin->GetIconCache( &szIcon, &pIconCache );

		static POINT pt = { 4, szBorder.cy + 4 };
		pIconCache->DrawIcon( &pt, m_pVP->icon, m_pVP->iconLibrary, pCanvas );
	}

	_ASSERTMEM( _CrtCheckMemory( ) );

	return S_OK;
}

STDMETHODIMP cPanel::Reformat()
{
	// Reset the size
	CComPtr< IPluginSite > pPlugin;
	m_pSite->get_PluginSite( &pPlugin );

	SIZE szScreen;
	pPlugin->GetScreenSize( &szScreen );

	RECT rc = { m_pVP->left, m_pVP->top, m_pVP->left + m_pVP->width, m_pVP->top + m_pVP->height };

	m_pSite->put_Position( &rc );

	RECT rcCloseBtn = { m_pVP->width - 16, 0, m_pVP->width, 16 };	
	CComPtr< ILayerSite > pCloseBtnLS;
	m_pSite->get_Child(1, ePositionByID, &pCloseBtnLS);

	pCloseBtnLS->put_Position(&rcCloseBtn);
	
	RECT rcIncBtn = { m_pVP->width - 32, 0, m_pVP->width - 32 + 16, 16 };	
	CComPtr< ILayerSite > pButtonInc;
	m_pSite->get_Child(2, ePositionByID, &pButtonInc);
	pButtonInc->put_Position( &rcIncBtn );

	RECT rcDecBtn = { m_pVP->width - 48, 0, m_pVP->width - 48 + 16, 16 };	
	CComPtr< ILayerSite > pButtonDec;
	m_pSite->get_Child(3, ePositionByID, &pButtonDec);
	pButtonDec->put_Position( &rcDecBtn );

	if( m_nActiveView != -1 )
	{
		// Position the active view
		SIZE szBorder;
		m_pBorder->get_Size( &szBorder );

		CComPtr< ILayerSite > pActive;
		m_pSite->get_Child( m_nActiveView, ePositionByID, &pActive );

		RECT rcChild = { 0, 24 + szBorder.cy, m_pVP->width, m_pVP->height - szBorder.cy };
		pActive->put_Position( &rcChild );
	}

	return S_OK;
}

STDMETHODIMP cPanel::AddView(long nViewID, ILayer *pLayer)
{
	_ASSERTE( pLayer != NULL );

	LayerParams p = { nViewID, { 0, 0, 0, 0 }, eRenderClipped };

	// Set up the layer - note that it is not visible
	return m_pSite->CreateChild( &p, pLayer );
}

STDMETHODIMP cPanel::ActivateView(long nViewID, ViewParams *pParams, long *pView)
{
	// Hide the current view by resizing to 0,0
	hideView();

	m_pVP = pParams;

	m_pcView = (cView*)pView;

	VARIANT_BOOL isTransparent=VARIANT_FALSE ;
	if (m_pcView)	m_pcView->get_Transparent(&isTransparent) ;
	put_Transparent(isTransparent) ;

	if( m_pVP->alpha == -1 )
		m_pSite->put_Alpha( m_Alpha );
	else
		m_pSite->put_Alpha( m_pVP->alpha );


#ifdef _DEBUG
	// Make sure the child exists
	CComPtr< ILayerSite > pChildSite;
	_ASSERTE( SUCCEEDED( m_pSite->get_Child( nViewID, ePositionByID, &pChildSite ) ) );
#endif

	// Locate the child
	m_nActiveView = nViewID;

	// Trick it into reformatting next frame
	static RECT rcBig = { 0, 0, 1, 1 };
	m_pSite->put_Position( &rcBig );

	// Pop us to the front
	m_pSite->moveToFront();

	return S_OK;
}

STDMETHODIMP cPanel::RemoveView( long nViewID )
{
	if( nViewID == m_nActiveView )
		// If this is the current view, run and hide
		Deactivate();

	CComPtr< ILayerSite > pChildSite;
	HRESULT hRes = m_pSite->get_Child( nViewID, ePositionByID, &pChildSite );
	_ASSERTE( SUCCEEDED( hRes ) );
	if( SUCCEEDED( hRes ) )
	pChildSite->Destroy();
	else
		return E_FAIL;

	return S_OK;
}

void cPanel::onCloseAccepted(long nID)
{
	// We should only be getting commands from the button
	_ASSERTE( nID == 1 );

	Deactivate();
}

void cPanel::onAlphaInc(long nID)
{
	// We should only be getting commands from the button
	_ASSERTE( nID == 2 );

	if(m_pVP->alpha == -1 )
	{
		m_pVP->alpha = m_Alpha + 5;
		m_pSite->put_Alpha( m_pVP->alpha );
	}
	else 
	{
		m_pVP->alpha += 5;
		
		if( m_pVP->alpha > 255 )
			m_pVP->alpha = 255;
		
		m_pSite->put_Alpha( m_pVP->alpha );
	}
}

void cPanel::onAlphaDec(long nID)
{
	// We should only be getting commands from the button
	_ASSERTE( nID == 3 );

	if(m_pVP->alpha == -1 )
	{
		m_pVP->alpha = m_Alpha - 5;
		m_pSite->put_Alpha( m_pVP->alpha );
	}
	else 
	{
		m_pVP->alpha -= 5;
		
		if( m_pVP->alpha < 0 )
			m_pVP->alpha = 0;
		
		m_pSite->put_Alpha( m_pVP->alpha );
	}
}

STDMETHODIMP cPanel::get_ActiveView(long *pVal)
{
	_ASSERTE( pVal != NULL );

	*pVal = m_nActiveView;

	return S_OK;
}

STDMETHODIMP cPanel::LoadView(long nViewID, IView *pView, IUnknown *pSchema)
{
	_ASSERTE( pView != NULL );
	_ASSERTE( pSchema != NULL );

	long nAssigned;

	// Set up the layer - note that it is not visible
	return pView->LoadControl( m_pSite, nViewID, pSchema, &nAssigned );
}

STDMETHODIMP cPanel::LoadViewEx(long nViewID, IView *pView, IUnknown *pSchema, long lViewFlags)
{
	_ASSERTE( pView != NULL );
	_ASSERTE( pSchema != NULL );

	long nAssigned;

	if( lViewFlags & eTransparent )
		m_bTransparent = true;

	// Set up the layer - note that it is not visible
	return pView->LoadControl( m_pSite, nViewID, pSchema, &nAssigned );
}

STDMETHODIMP cPanel::Deactivate()
{
	if( m_nActiveView == -1 )
		// No active view currently
		return S_OK;

	// Hide the current view by resizing to 0,0
	hideView();

	// Hide the entire panel
	static RECT rcHide = { 0, 0, 0, 0 };
	m_pSite->put_Position( &rcHide );

	m_nActiveView = -1;

	return S_OK;
}

STDMETHODIMP cPanel::putref_Sink(IPanelSink *newVal)
{
	m_pSink = newVal;

	return S_OK;
}

STDMETHODIMP cPanel::MouseEvent(long nMsg, long wParam, long lParam)
{
	static RECT rcTemp;
	static SIZE size;

	switch(nMsg)
	{
		case WM_LBUTTONDOWN:
			{

				// Pop us to the front
				m_pSite->moveToFront();

				SIZE szBorder;
				m_pBorder->get_Size( &szBorder );

				POINTS ptm;
				ptm = MAKEPOINTS(lParam);
				
				if( !cManager::_p->m_bContainer )
					ptm.y-=28;
				
				if((ptm.x>=m_pVP->left+szBorder.cy) && (ptm.x<=m_pVP->left+m_pVP->width-szBorder.cy) && (ptm.y>=m_pVP->top+szBorder.cy) && (ptm.y<=m_pVP->top+28))
				{
					m_DeltaX = ptm.x-m_pVP->left;
					m_DeltaY = ptm.y-m_pVP->top;
					m_bDragging = true;
				}
				else
				{
					if(m_pcView->Fire_Size()==VARIANT_TRUE)
					{
						if((ptm.x>=m_pVP->left) && (ptm.x<=m_pVP->left+m_pVP->width))
						{
							if((ptm.y>=m_pVP->top) && (ptm.y<=m_pVP->top+szBorder.cy))
							{
								m_bSizingYT = true;
								m_DeltaY = ptm.y-m_pVP->top;
							} else if((ptm.y>=m_pVP->top+m_pVP->height-szBorder.cy) && (ptm.y<=m_pVP->top+m_pVP->height))
							{
								m_bSizingYB = true;
								m_DeltaY = m_pVP->top+m_pVP->height-ptm.y;
							}
						}

						if((ptm.y>=m_pVP->top) && (ptm.y<=m_pVP->top+m_pVP->height))
						{
							if((ptm.x>=m_pVP->left) && (ptm.x<=m_pVP->left+szBorder.cy))
							{
								m_bSizingXL = true;
								m_DeltaX = ptm.x-m_pVP->left;
							} else if((ptm.x>=m_pVP->left+m_pVP->width-szBorder.cy) && (ptm.x<=m_pVP->left+m_pVP->width))
							{
								m_bSizingXR = true;
								m_DeltaX = m_pVP->left+m_pVP->width-ptm.x;
							}
						}
					}
				}
				break;
			}

		case WM_LBUTTONUP:
			{
				m_bDragging = m_bSizingXL = m_bSizingXR = m_bSizingYT = m_bSizingYB = false;
				break;
			}

		case WM_MOUSEMOVE:
			{
				if(wParam==MK_LBUTTON)
				{
					bool bUpdate = false;
					POINTS ptm;
					ptm = MAKEPOINTS(lParam);
					
					if( !cManager::_p->m_bContainer )
						ptm.y-=28;

					if(m_bDragging)
					{
						m_pVP->left = ptm.x-m_DeltaX;
						m_pVP->top = ptm.y-m_DeltaY;

						/* Drakier: make sure they aren't being bad little kittens and
												moving the view offscreen! */
						// Drakier: Get the pSite and Screen Size

						CComPtr< IPluginSite > pPlugin;
						CComPtr< IACHooks > pHooks;
						m_pSite->get_PluginSite( &pPlugin );

						SIZE szScreen, sz;
						pPlugin->GetScreenSize( &sz );
						szScreen.cx = sz.cx;
						szScreen.cy = sz.cy;

						long lX = sz.cx, lY = sz.cy;
						
						// Drakier: if we are not in the container, get the 3D Area
						if ( !cManager::_p->m_bContainer )
						{
							pPlugin->get_Hooks( &pHooks );
							pHooks->get_Area3DHeight( &lY );
							pHooks->get_Area3DWidth( &lX );
							pHooks.Release();
						}
						pPlugin.Release();

						// Drakier: if we are in the container, or the 3D area's are NULL
						if ( (cManager::_p->m_bContainer) || (&lX == NULL) || (&lY == NULL) )
						{
							szScreen.cx = sz.cx - 308;	// 308 = PANEL_SIZE
							szScreen.cy = sz.cy;
						}
						else // Drakier: If everything comes out right and we are not in container
						{
							if( (&lX != NULL) &&  (lX > 0) && (lX < 5000) )
								szScreen.cx = lX;
							if( (&lY != NULL) && (lY > 0) && (lY < 5000) )
								szScreen.cy = lY;
						}

						if ( m_pVP->left < 0 )
							m_pVP->left = 0;
						if ( m_pVP->top < 0 )
							m_pVP->top = 0;
						if ( (m_pVP->left + m_pVP->width) > szScreen.cx )
							m_pVP->left = szScreen.cx - m_pVP->width;
						if ( (m_pVP->top + m_pVP->height) > szScreen.cy )
							m_pVP->top = szScreen.cy - m_pVP->height;

						bUpdate = true;
					}
					else 
					{
						if(m_bSizingYT)
						{
							rcTemp.bottom = m_pVP->height + m_pVP->top - (ptm.y-m_DeltaY);
							rcTemp.top = ptm.y-m_DeltaY;

							if(rcTemp.bottom > 34)
							{
								m_pVP->height = rcTemp.bottom;
								m_pVP->top = rcTemp.top;
							}
							else
							{
								m_pVP->top = (m_pVP->top + m_pVP->height) - 34;
								m_pVP->height = 34;
							}

							bUpdate = true;
						}
						else if(m_bSizingYB)
						{
							rcTemp.bottom = ptm.y-m_pVP->top+m_DeltaY;
							
							if(rcTemp.bottom > 34)
								m_pVP->height = rcTemp.bottom;
							else
								m_pVP->height = 34;

							bUpdate = true;
						}

						if(m_bSizingXL)
						{
							rcTemp.right = m_pVP->width + m_pVP->left - (ptm.x-m_DeltaX);
							rcTemp.left = ptm.x-m_DeltaX;
							
							m_pTitle->MeasureText(m_pVP->label, &size);

							if(rcTemp.right > size.cx + 48)
							{
								m_pVP->width = rcTemp.right;
								m_pVP->left = rcTemp.left;
							}
							else
							{
								m_pVP->left = (m_pVP->left + m_pVP->width) - (size.cx + 48);
								m_pVP->width = size.cx+48;
							}

							bUpdate = true;
						}
						else if(m_bSizingXR)
						{
							rcTemp.right = ptm.x-m_pVP->left+m_DeltaX;
							
							m_pTitle->MeasureText(m_pVP->label, &size);

							if(rcTemp.right > size.cx + 48)
								m_pVP->width = rcTemp.right;
							else
								m_pVP->width = size.cx + 48;

							bUpdate = true;
						}
					}

					if(bUpdate)
					{
						if(!m_bDragging)
						{
							//RECT rc = { m_pcView->m_VP.left, m_pcView->m_VP.top, m_pcView->m_VP.width, m_pcView->m_VP.height };
							m_pcView->Fire_Sizing(/*m_pcView*//*&m_pcView->m_VP*//*m_pcView->m_VP.left, m_pcView->m_VP.top,*/ 0, 0, m_pcView->m_VP.width, m_pcView->m_VP.height-34);
						}
						static RECT rcBig = { 0, 0, 1, 1 };
						m_pSite->put_Position( &rcBig );
					}
				}
				break;
			}
	}
	return S_OK;
}

STDMETHODIMP cPanel::get_Transparent(VARIANT_BOOL *pVal)
{
	*pVal = ( m_bTransparent ? VARIANT_TRUE : VARIANT_FALSE );
	return S_OK;
}

STDMETHODIMP cPanel::put_Transparent(VARIANT_BOOL newVal)
{
	if( newVal == VARIANT_FALSE )
		m_bTransparent = false;
	else
		m_bTransparent = true;

	if( m_pVP->alpha == -1 )
		m_pSite->put_Alpha( m_Alpha );
	else
		m_pSite->put_Alpha( m_pVP->alpha );

	m_pSite->Invalidate();
	m_pSite->Reformat();

	return S_OK;
}

STDMETHODIMP cPanel::put_Params(ViewParams *newVal)
{
	if( newVal == NULL )
		return E_POINTER;

	m_pVP = newVal;
	return S_OK;
}
