// Implementation file for the definition of a characteristic base control
/////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"

#include "Controls\CTL_BCL.hpp"

#include "Controls\CTL_Ctl.hpp"

//External Modules
#include "CTL_ErO.hpp"
//End of External Modules

#define C_SPACE_BETWEEN_CONTROLS	2

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


//**************************************************************************************
CTL_Editor_BaseControlList::CTL_Editor_BaseControlList(BOOL _bMustDestroyElements /*= TRUE*/)
{
	m_pri_bMustDestroyElements = _bMustDestroyElements;
}

//**************************************************************************************
CTL_Editor_BaseControlList::~CTL_Editor_BaseControlList()
{
	if ( m_pri_bMustDestroyElements )
		m_pri_fn_vEmptyList();
}

//**************************************************************************************
CTL_Editor_BaseControl *CTL_Editor_BaseControlList::m_pub_fn_pclAddControlAtHead(CTL_BaseWindowsControl *_pclBaseWindowsControl,
																															CWnd *_pclWnd,
																															CTL_Editor_Control *_pclParentControl,
																															CTL_tdeBaseControlDisplayType _eDisplayType,
																															unsigned char _ucPercentWidth,
																															unsigned short _uwFixedWidth,
																															unsigned short _uwHeight,
																															BOOL _bSamePlaceAsNext /*= FALSE*/,
																															BOOL _bGoToNextLineAfterMe /*= FALSE*/)
{
	CTL_Editor_BaseControl *pclNewElement = new CTL_Editor_BaseControl(	_pclBaseWindowsControl, 
																																			_pclWnd,
																																			_pclParentControl,
																																			_eDisplayType,
																																			_ucPercentWidth, 
																																			_uwFixedWidth,
																																			_uwHeight,
																																			_bSamePlaceAsNext,
																																			_bGoToNextLineAfterMe);
	
	AddHead(pclNewElement);

	return pclNewElement;
}

//**************************************************************************************
CTL_Editor_BaseControl *CTL_Editor_BaseControlList::m_pub_fn_pclAddControlAtTail(CTL_BaseWindowsControl *_pclBaseWindowsControl,
																															CWnd *_pclWnd,
	 																														CTL_Editor_Control *_pclParentControl,
																															CTL_tdeBaseControlDisplayType _eDisplayType,
																															unsigned char _ucPercentWidth,
																															unsigned short _uwFixedWidth,
																															unsigned short _uwHeight,
																															BOOL _bSamePlaceAsNext /*= FALSE*/,
																															BOOL _bGoToNextLineAfterMe /*= FALSE*/)
{
	CTL_Editor_BaseControl *pclNewElement = new CTL_Editor_BaseControl(	_pclBaseWindowsControl, 
																																			_pclWnd,
																																			_pclParentControl,
																																			_eDisplayType,
																																			_ucPercentWidth, 
																																			_uwFixedWidth,
																																			_uwHeight,
																																			_bSamePlaceAsNext,
																																			_bGoToNextLineAfterMe);
	
	AddTail(pclNewElement);

	return pclNewElement;
}

//**************************************************************************************
CTL_Editor_BaseControl *CTL_Editor_BaseControlList::m_pub_fn_pclAddControlAtPosition(unsigned char _ucTargettedPosition,
																															CTL_BaseWindowsControl *_pclBaseWindowsControl,
																															CWnd *_pclWnd,
																															CTL_Editor_Control *_pclParentControl,
																															CTL_tdeBaseControlDisplayType _eDisplayType,
																															unsigned char _ucPercentWidth,
																															unsigned short _uwFixedWidth,
																															unsigned short _uwHeight,
																															BOOL _bSamePlaceAsNext /*= FALSE*/,
																															BOOL _bGoToNextLineAfterMe /*= FALSE*/)
{
	CTL_Editor_BaseControl *pclNewElement = new CTL_Editor_BaseControl(	_pclBaseWindowsControl, 
																																			_pclWnd,
																																			_pclParentControl,
																																			_eDisplayType,
																																			_ucPercentWidth, 
																																			_uwFixedWidth,
																																			_uwHeight,
																																			_bSamePlaceAsNext,
																																			_bGoToNextLineAfterMe);
	
	//Searches for the right Position
	BOOL bFound = FALSE;
	unsigned char ucCurrentPosition = 0;
	POSITION pos = GetHeadPosition();
	while ( (pos != NULL) && (!bFound) )
	{
		if ( ucCurrentPosition < _ucTargettedPosition )
		{
			GetNext(pos);
			ucCurrentPosition ++;
		}
		else
			bFound = TRUE;
	}

	InsertAfter(pos, pclNewElement);

	return pclNewElement;
}

//**************************************************************************************
void CTL_Editor_BaseControlList::m_pub_fn_vComputeZoneOfAllBaseControls(long _lTotalWidth,
																																				enum CTL_eControlSpacingType _eSpacingType)
{
	CTL_Editor_BaseControlList *pclTempList = new CTL_Editor_BaseControlList(FALSE);
	BOOL bMustGoOn = TRUE;

	//Builds temp sub-list with one-line controls
	CTL_Editor_BaseControl *pclBC;
	BOOL bNextLineFound = FALSE;
	POSITION GlobalPos = GetHeadPosition();
	POSITION KeepedPos = GlobalPos;
	while ( (GlobalPos != NULL) && (!bNextLineFound) )
	{
		pclBC	= GetNext(GlobalPos);

		bNextLineFound = pclBC->m_pri_bBeginsOnNextLine;

		if ( !bNextLineFound )
		{
			KeepedPos = GlobalPos;

			pclTempList->AddTail(pclBC);
		}
	}

	while ( bMustGoOn )
	{
		//Adjusts Total witdh
		long lTotalWidth = _lTotalWidth - pclTempList->m_pri_fn_wComputeTotalSizeOfSpaces();

		//Resets computed values for base controls
		CTL_Editor_BaseControl *pclCurrentBC;
		POSITION pos = pclTempList->GetHeadPosition();
		while ( pos != NULL )
		{
			pclCurrentBC = pclTempList->GetNext(pos);
		
			pclCurrentBC->m_pri_cComputedPercentage = CTL_C_BASE_CONTROL_INVALID_PERCENTAGE;
			pclCurrentBC->m_pri_lComputedWidth = 0;
		}

		//Computes total size of "non percentaged" sizes, and each of their sizes
		long lTotalFixedSize = pclTempList->m_pri_fn_wComputeTotalSizeOfFixedSizeControlsAndTheirSize(_eSpacingType);
		
		if ( _eSpacingType != CTL_SPACING_TYPE__AUTO )
		{
			ERROR_ASSERT( lTotalFixedSize < lTotalWidth );
			lTotalWidth -= lTotalFixedSize;

			//Computes percentages for the Base Controls which are "percentaged", and each of their sizes
			pclTempList->m_pri_fn_vComputeTruePercentagesAndSizes(lTotalWidth);
		}

		//Computes Zone for all Base Controls
		pos = pclTempList->GetHeadPosition();
		while ( pos != NULL )
		{
			pclCurrentBC = pclTempList->GetNext(pos);
			
			pclCurrentBC->m_pub_fn_vComputeBaseControlZone();
		}

		//Builds the next sub-list
		if ( GlobalPos != NULL )
		{
			pclTempList->RemoveAll();
 			GlobalPos = KeepedPos;
			bNextLineFound = FALSE;

			//To avoid the first, for which we are sure 'BeginsOnNextLine' is TRUE
			pclBC	= GetNext(GlobalPos);
			pclTempList->AddTail(pclBC);
			KeepedPos = GlobalPos;

			while ( (GlobalPos != NULL) && (!bNextLineFound) )
			{
				pclBC	= GetNext(GlobalPos);

				bNextLineFound = pclBC->m_pri_bBeginsOnNextLine;

				if ( !bNextLineFound )
				{
					KeepedPos = GlobalPos;

					pclTempList->AddTail(pclBC);
				}
			}
		}
		else
			bMustGoOn = FALSE;
	}

	//Will not destroy 
	delete pclTempList;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////
// Private Functions //
///////////////////////

//**************************************************************************************
void CTL_Editor_BaseControlList::m_pri_fn_vEmptyList()
{
	POSITION pos = GetHeadPosition();
	while ( pos != NULL )
		delete GetNext(pos);

	RemoveAll();
}

//**************************************************************************************
short CTL_Editor_BaseControlList::m_pri_fn_wComputeTotalSizeOfSpaces()
{
	short wTotalSize = 0;

	POSITION pos = GetHeadPosition();
	while ( pos != NULL )
	{
		GetNext(pos);

		if ( pos != NULL )
			wTotalSize += C_SPACE_BETWEEN_CONTROLS;
	}

	return wTotalSize;
}

//**************************************************************************************
short CTL_Editor_BaseControlList::m_pri_fn_wComputeTotalOfPercentages()
{
	short wTotalPercentages = 0;

	CTL_Editor_BaseControl *pclCurrentBC;
	POSITION pos = GetHeadPosition();
	while ( pos != NULL )
	{
		pclCurrentBC = GetNext(pos);

		if ( !pclCurrentBC->m_pri_bSamePlaceAsNext )
			if ( pclCurrentBC->m_pub_fn_bCanBeDisplayed() )
				wTotalPercentages += pclCurrentBC->m_pri_ucPercentWidth;
	}

	return wTotalPercentages;
}

//**************************************************************************************
short CTL_Editor_BaseControlList::m_pri_fn_wComputeTotalSizeOfFixedSizeControlsAndTheirSize(enum CTL_eControlSpacingType _eSpacingType)
{
	short wTotalSize = 0;

	CTL_Editor_BaseControl *pclCurrentBC;
	POSITION pos = GetHeadPosition();
	while ( pos != NULL )
	{
		pclCurrentBC = GetNext(pos);

		if ( pclCurrentBC->m_pub_fn_bCanBeDisplayed() )
		{
			//Computes size
			switch ( pclCurrentBC->m_pub_fn_tdeGetDisplayType() )
			{
			////
			case CTL_BASE_CONTROL_DISPLAY_TYPE__ALWAYS_FIXED:
 				pclCurrentBC->m_pri_lComputedWidth = pclCurrentBC->m_pri_uwFixedWidth;
				break;
			
			////
			case CTL_BASE_CONTROL_DISPLAY_TYPE__ALWAYS_PERCENTAGED:
 				pclCurrentBC->m_pri_lComputedWidth = 0;	//will be computed later !
				break;
			
			////
			case CTL_BASE_CONTROL_DISPLAY_TYPE__USE_CALLBACK:
 				{
					switch ( _eSpacingType )
					{
					/////
					case CTL_SPACING_TYPE__SINGLE_LINE:
					case CTL_SPACING_TYPE__MULTI_LINE:
 						pclCurrentBC->m_pri_lComputedWidth = 0;	//will be computed later !
						break;

					/////
					case CTL_SPACING_TYPE__AUTO:
					case CTL_SPACING_TYPE__FIXED_SIZE:
 						pclCurrentBC->m_pri_lComputedWidth = pclCurrentBC->m_pri_td_p_fn_lGetSize_CallBack(pclCurrentBC);
						break;
					};
				}
				break;

			////
			case CTL_BASE_CONTROL_DISPLAY_TYPE__NORMAL:
				{
					switch ( _eSpacingType )
					{
					/////
					case CTL_SPACING_TYPE__SINGLE_LINE:
					case CTL_SPACING_TYPE__MULTI_LINE:
 						pclCurrentBC->m_pri_lComputedWidth = 0;	//will be computed later !
						break;

					/////
					case CTL_SPACING_TYPE__AUTO:
					case CTL_SPACING_TYPE__FIXED_SIZE:
 						pclCurrentBC->m_pri_lComputedWidth = pclCurrentBC->m_pri_uwFixedWidth;
						break;
					};
				}
				break;
			};

			//Adds it to the total size
			wTotalSize += (short)pclCurrentBC->m_pri_lComputedWidth;
		}
	}

	return wTotalSize;
}

//**************************************************************************************
// !!!  MUST ALWAYS BE CALLED AFTER 'm_pri_fn_wComputeTotalSizeOfFixedSizeControlsAndTheirSize'	!!!
///////////////////////////////////////////////////////////////////////////////////////////////////
void CTL_Editor_BaseControlList::m_pri_fn_vComputeTruePercentagesAndSizes(long _lTotalWidth)
{
	short wTotalPercentages = m_pri_fn_wComputeTotalOfPercentages();

	if ( wTotalPercentages != 0 )
	{
		CTL_Editor_BaseControl *pclCurrentBC;
		POSITION pos = GetHeadPosition();
		while ( pos != NULL )
		{
			pclCurrentBC = GetNext(pos);

			if ( pclCurrentBC->m_pri_lComputedWidth == 0 )
				if ( pclCurrentBC->m_pub_fn_bCanBeDisplayed() )
					pclCurrentBC->m_pri_lComputedWidth = (_lTotalWidth * pclCurrentBC->m_pri_ucPercentWidth) / wTotalPercentages;
		}
	}
}

//**************************************************************************************
BOOL CTL_Editor_BaseControlList::m_pri_fn_bAllBaseControlsPercentagesInitialized()
{
	BOOL bReturn = TRUE;

	POSITION pos = GetHeadPosition();
	while ( (pos != NULL) && (bReturn) )
		bReturn = ( GetNext(pos)->m_pri_cComputedPercentage != CTL_C_BASE_CONTROL_INVALID_PERCENTAGE );

	return bReturn;
}



