//
//	Copyright © 2007 Nemetschek North America 
//	All Rights Reserved.
//
// Created by Bozhidar Stanchev

#include "StdAfx.h"
//#include "VWTextBlockObj.h"

using namespace VWFC::Math;
using namespace VWFC::Tools;
using namespace VWFC::VWObjects;

VWTextBlockObj::VWTextBlockObj(const TXString& strText)
{
	fOriginPt.SetPoint( 0, 0 );
	fhObject		= ::GS_CreateTextBlock( gCBP, strText, fOriginPt, false, 0 );

	VWFC_ASSERT( fhObject );
	if ( fhObject == NULL )
		THROW_VWFC_EXCEPTION( VWCannotCreateObjectException, 0, "cannot create text block" );
}

VWTextBlockObj::VWTextBlockObj(const TXString& strText, const VWPoint2D& originPt)
{
	fOriginPt		= originPt;
	fhObject		= ::GS_CreateTextBlock( gCBP, strText, fOriginPt, false, 0 );

	VWFC_ASSERT( fhObject );
	if ( fhObject == NULL )
		THROW_VWFC_EXCEPTION( VWCannotCreateObjectException, 0, "cannot create text block" );
}

VWTextBlockObj::VWTextBlockObj(MCObjectHandle hTextBlock)
{
	VWFC_ASSERT( VWTextBlockObj::IsTextBlockObject( hTextBlock ) );

	if ( ! VWTextBlockObj::IsTextBlockObject( hTextBlock ) )
		THROW_VWFC_EXCEPTION( VWBadObjectTypeException, 0, "bad handle type when creating" );

	fhObject		= hTextBlock;
	VWFC_ASSERT( fhObject != nil );
}

VWTextBlockObj::VWTextBlockObj(const VWTextBlockObj& src)
{
	fhObject		= src.fhObject;
	fOriginPt		= src.fOriginPt;
}

VWTextBlockObj::~VWTextBlockObj()
{
}

VWTextBlockObj& VWTextBlockObj::operator=(const VWTextBlockObj& src)
{
	fhObject		= src.fhObject;
	fOriginPt		= src.fOriginPt;
	return *this;
}

bool VWTextBlockObj::IsTextBlockObject(MCObjectHandle hObj)
{
	short	type = ::GS_GetObjectType( gCBP, hObj );
	return	( type == kTextNode );
}

bool VWTextBlockObj::InsertText(const TXString& strAdd, size_t beforeIndex /*= 0*/)
{
	// get text block chars to a buffer
	size_t	textLen		= this->GetTextLength();

	bool	bAdded	= false;
	// Note 'GS_AddTextFromBuffer' doesnt work if 'GS_CreateTextBlock' creates empty text!
	if ( textLen == 0 ) {

		size_t	strLen	= strAdd.GetLength();
		if ( strLen > 0 ) {

			// delete current text block
			this->DeleteObject( false );

			// create a new text block
			fhObject	= ::GS_CreateTextBlock( gCBP, strAdd, fOriginPt, false, 0 );

			VWFC_ASSERT( fhObject );
			bAdded	= ( fhObject != NULL );
		}
	}
	else {

		size_t	strLen	= strAdd.GetLength();
		if ( strLen > 0 ) {
			bAdded	= ::GS_AddTextFromBuffer( gCBP, fhObject, (long) beforeIndex, (void*) (const char*) strAdd, (long) strLen );
		}
	}

	return bAdded;
}

bool VWTextBlockObj::AppendText(const TXString& strAdd)
{
	return this->InsertText( strAdd, this->GetTextLength() );
}

void VWTextBlockObj::DeletePartOfText(size_t firstIndex, size_t numChars)
{
	size_t	textLen		= this->GetTextLength();
	VWFC_ASSERT( textLen > firstIndex && textLen > numChars );
	::GS_DeleteText( gCBP, fhObject, (long) firstIndex, (long) numChars );
}

void VWTextBlockObj::DeleteText()
{
	this->DeletePartOfText( 0, this->GetTextLength() );
}

size_t VWTextBlockObj::GetTextLength() const
{
	return (size_t) ::GS_GetTextLength( gCBP, fhObject );
}

TXString VWTextBlockObj::GetText() const
{
	long	textLen		= this->GetTextLength();
	char*	szBuffer	= (char*) NEW_DATA( textLen + 1 );
	VWFC_VERIFY( ::GS_GetTextCharsToBuffer( gCBP, fhObject, szBuffer, textLen ) );

	TXString	textStr( szBuffer, textLen );
	DELETE_DATA( szBuffer );

	return	textStr;
}

size_t VWTextBlockObj::GetNearestCharIndex(const VWPoint2D& pt) const
{
	size_t resNum	= (size_t) ::GS_GetCharNumFromPoint( gCBP, fhObject, pt );
	VWFC_ASSERT( resNum >= 0 && resNum < this->GetTextLength() );
	return resNum;
}

void VWTextBlockObj::SetTextColor(const CRGBColor& color)
{
	this->SetCharsColor( 0, this->GetTextLength(), color.GetColorIndex() );
}

void VWTextBlockObj::SetTextFontIndex(short textFontIndex)
{
	this->SetCharsFontIndex( 0, this->GetTextLength(), textFontIndex );
}

void VWTextBlockObj::SetTextSize(double dTextSize)
{
	this->SetCharsSize( 0, this->GetTextLength(), dTextSize );
}

void VWTextBlockObj::SetTextSizeByPoint(double dPointSize)
{
	double	dCharSize	= ::GS_PagePointsToCoordLength( gCBP, dPointSize );
	this->SetCharsSize( 0, this->GetTextLength(), dCharSize );
}

void VWTextBlockObj::SetTextStyle(ETextStyle style)
{
	this->SetCharsStyle( 0, this->GetTextLength(), style );
}

CRGBColor VWTextBlockObj::GetCharColor(size_t charNum) const
{
	ColorRef	charColor;
	::GS_GetTextColor( gCBP, fhObject, (long) charNum, charColor );
	return	CRGBColor( charColor );
}

short VWTextBlockObj::GetCharFontIndex(size_t charNum) const
{
	short	charFontIndex;
	::GS_GetTextFontIndex( gCBP, fhObject, (long) charNum, charFontIndex );
	return	charFontIndex;
}

double	VWTextBlockObj::GetCharSize(size_t charNum) const
{
	double	charSize;
	::GS_GetTextSize( gCBP, fhObject, (long) charNum, charSize );
	return	charSize;
}

ETextStyle VWTextBlockObj::GetCharStyle(size_t charNum) const
{
	unsigned char	charStyle;
	::GS_GetTextStyle( gCBP, fhObject, (long) charNum, charStyle );
	return	(ETextStyle) charStyle;
}

void VWTextBlockObj::SetCharsColor(size_t firstIndex, size_t numChars, const CRGBColor& color)
{
	::GS_SetTextColor( gCBP, fhObject, (long) firstIndex, (long) numChars, color.GetColorIndex() );
}

void VWTextBlockObj::SetCharsFontIndex(size_t firstIndex, size_t numChars, short fontIndex)
{
	::GS_SetTextFontIndex( gCBP, fhObject, (long) firstIndex, (long) numChars, fontIndex );
}

void VWTextBlockObj::SetCharsSize(size_t firstIndex, size_t numChars, double dCharSize)
{
	::GS_SetTextSize( gCBP, fhObject, (long) firstIndex, (long) numChars, dCharSize );
}

void VWTextBlockObj::SetCharsSizeByPoint(size_t firstIndex, size_t numChars, double dPointSize)
{
	double	dCharSize	= ::GS_PagePointsToCoordLength( gCBP, dPointSize );
	::GS_SetTextSize( gCBP, fhObject, (long) firstIndex, (long) numChars, dCharSize );
}

void VWTextBlockObj::SetCharsStyle(size_t firstIndex, size_t numChars, ETextStyle style)
{
	::GS_SetTextStyle( gCBP, fhObject, (long) firstIndex, (long) numChars, style );
}

CRGBColor VWTextBlockObj::GetNearestCharColor(const VWPoint2D& pt) const
{
	size_t	charNum = (size_t) ::GS_GetCharNumFromPoint( gCBP, fhObject, pt );
	return	this->GetCharColor( charNum );
}

short VWTextBlockObj::GetNearestCharFontIndex(const VWPoint2D& pt) const
{
	size_t	charNum = (size_t) ::GS_GetCharNumFromPoint( gCBP, fhObject, pt );
	return	this->GetCharFontIndex( charNum );
}

double	VWTextBlockObj::GetNearestCharSize(const VWPoint2D& pt) const
{
	size_t	charNum = (size_t) ::GS_GetCharNumFromPoint( gCBP, fhObject, pt );
	return	this->GetCharSize( charNum );
}

ETextStyle VWTextBlockObj::GetNearestCharStyle(const VWPoint2D& pt) const
{
	size_t	charNum = (size_t) ::GS_GetCharNumFromPoint( gCBP, fhObject, pt );
	return	(ETextStyle) this->GetCharStyle( charNum );
}

ETextHorzAlign VWTextBlockObj::GetTextJustification() const
{
	short	textJust;
	::GS_GetTextJustification( gCBP, fhObject, textJust );
	return	(ETextHorzAlign) textJust;
}

void VWTextBlockObj::SetTextJustification(ETextHorzAlign textJust)
{
	::GS_SetTextJustification( gCBP, fhObject, textJust );
}

void VWTextBlockObj::GetTextOrientation(double& outAngle, bool& outVertFlip)
{
	short		flipState;
	::GS_GetTextOrientationN( gCBP, fhObject, outAngle, flipState );

	outVertFlip		= flipState == kTextVerticalFlip;
}

void VWTextBlockObj::SetTextOrientation(double dAngle, bool bVertFlip)
{
	::GS_SetTextOrientationN( gCBP, fhObject, dAngle, bVertFlip ? kTextVerticalFlip : kTextNoFlip );
}

double VWTextBlockObj::GetTextWidth() const
{
	double	textWidth;
	::GS_GetTextWidth( gCBP, fhObject, textWidth );
	return	textWidth;
}

void VWTextBlockObj::SetTextWidth(double dWidth)
{
	::GS_SetTextWidth( gCBP, fhObject, dWidth );
}

bool VWTextBlockObj::IsTextWrapped() const
{
	Boolean	bWrapped;
	::GS_GetTextWrap( gCBP, fhObject, bWrapped );
	return	bWrapped;
}

void VWTextBlockObj::SetTextWrap(bool bWrapped)
{
	::GS_SetTextWrap( gCBP, fhObject, bWrapped );
}

ETextVertAlign VWTextBlockObj::GetTextVerticalAlignment() const
{
	short	verticalAlignment;
	::GS_GetTextVerticalAlignment( gCBP, fhObject, verticalAlignment );
	return	(ETextVertAlign) verticalAlignment;
}

void VWTextBlockObj::SetTextVerticalAlignment(ETextVertAlign align)
{
	::GS_SetTextVerticalAlignment( gCBP, fhObject, align );
}

void VWTextBlockObj::GetTextVerticalSpacing(ETextVertSpacing& outSpacing, double& outHeight)
{
	short	spcing;
	::GS_GetTextVerticalSpacing( gCBP, fhObject, spcing, outHeight );
	outSpacing		= (ETextVertSpacing) spcing;
}

void VWTextBlockObj::SetTextVerticalSpacing(ETextVertSpacing spacing, double dHeight)
{
	::GS_SetTextVerticalSpacing( gCBP, fhObject, spacing, dHeight );
}