// ShapeElement.cpp: implementation of the ShapeElement class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "AG_MDA.h"
#include "ShapeElement.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPtrTempl<ShapeElement*> ShapeElement::m_AllShapes;
HANDLE ShapeElement::m_AccessSem = NULL;
ShapeElement::ShapeElement()
{
	if( m_AccessSem == NULL )
	{
		m_AccessSem = CreateSemaphore( NULL , 1 , 1 , NULL );
	}
	m_pShapeNamespace = NULL;
	ZeroMemory( &m_TextFont , sizeof(m_TextFont));
	m_FillColor = RGB( 255 , 255 , 0);//填充颜色
	m_FillStyle = 0;

	m_LineColor = RGB( 128 , 64 , 0);
	m_LineStyle = PS_SOLID;
	m_LineWidth = 1;

	m_Pos = CRect( 100 , 100 , 150 , 150 );
	
	m_TextBkMode = TRANSPARENT;
	m_TextColor = RGB( 0 , 0 , 0 );
	m_TextFont.lfCharSet = GB2312_CHARSET;
	strcpy( m_TextFont.lfFaceName , "宋体" );
	m_TextFont.lfHeight = 12;
	m_TextFont.lfItalic = FALSE;
	m_TextFont.lfUnderline = FALSE;
	m_TextFont.lfWeight = 400;

	//设置ID
	m_ID = 1;
	WaitForSingleObject( m_AccessSem , INFINITE );
	for( int i = 0 ; i <= m_AllShapes.GetUpperBound() ; i++)
	{
		ShapeElement *e = m_AllShapes.GetAt( i );
		if( e->m_ID >= m_ID ) m_ID = e->m_ID + 1;
	}

	m_AllShapes.Add( this );
	ReleaseSemaphore( m_AccessSem , 1 , NULL );
	m_pMarkElement = NULL;
	beUsed=false;
}

ShapeElement::~ShapeElement()
{
	WaitForSingleObject( m_AccessSem , INFINITE );
	for( int i = 0 ; i <= m_AllShapes.GetUpperBound() ; i ++ )
	{
		ShapeElement *p = m_AllShapes.GetAt( i );
		if( p == this )
		{
			m_AllShapes.RemoveAt( i );
			break;
		}
	}
	ReleaseSemaphore( m_AccessSem , 1 ,NULL );
	if( m_pMarkElement ) delete m_pMarkElement;
}

void ShapeElement::Draw(CDC *pDC)
{
	pDC->TextOut( 100, 100 , "你好");
	pDC->MoveTo( 100 , 100 );
	pDC->LineTo( 200 , 200 );
	pDC->Rectangle( CRect( 300 , 300 , 400 , 400 ));
	
	LOGFONT lf;
	lf = m_TextFont;
	lf.lfHeight -= 5;
	SetTempFont( pDC , lf );
	DrawTextLeft( CRect( 300 , 300 , 400 , 400 ), "天下乌鸦" ,pDC ,20);
	RestoreFont( pDC );

	lf = m_TextFont;
	lf.lfHeight += 5;
	SetTempFont( pDC , lf );
	DrawTextLeft( CRect( 300 , 400 , 400 , 500 ), "天下乌鸦" ,pDC ,20);
	RestoreFont( pDC );

	SetTempPen( pDC , 1 , RGB( 255 , 0 , 0 ));
	pDC->MoveTo( 300 , 400 );
	pDC->LineTo( 400 , 500);
	RestorePen( pDC );
}

void ShapeElement::DrawDefault(CDC *pDC)
{
	CPen pen , *oldPen;
	CFont font , *oldFont;
	CBrush brush , *oldBrush;
	COLORREF oldTextColor;
	int oldBkMode;

	pen.CreatePen( m_LineStyle , m_LineWidth , m_LineColor );
	font.CreateFontIndirect( &m_TextFont );
	if( !m_FillStyle )
	{
		brush.CreateSolidBrush( m_FillColor );
	}
	else
	{
		brush.CreateHatchBrush( m_FillStyle , m_FillColor );
	}

	oldBkMode = pDC->GetBkMode();
	pDC->SetBkMode( m_TextBkMode );
	oldTextColor = pDC->GetTextColor();
	oldPen = pDC->SelectObject( &pen );
	oldFont = pDC->SelectObject( &font );
	oldBrush = pDC->SelectObject( &brush );

	Draw( pDC );
	
	pDC->SelectObject( oldBrush );
	pDC->SelectObject( oldFont );
	pDC->SelectObject( oldPen );
	pDC->SetTextColor( oldTextColor );
	pDC->SetBkMode( oldBkMode );
}

void ShapeElement::DrawTextCenter(CRect r, CString txt, CDC *pDC , int marginX ,int marginY)
{
	int x,y;
	int dx,dy;
	CRect rect;
	CSize sz = pDC->GetTextExtent( txt );
	dx = r.right - r.left;
	dy = r.bottom - r.top;
	dx -= sz.cx ;
	dy -= sz.cy ;
	dx >>= 1;
	dy >>= 1;

	rect = r;
	rect.left += marginX;
	rect.right -= marginX;
	rect.top += marginY;
	rect.bottom -= marginY;

	x = r.left + dx;
	y = r.top + dy;

	pDC->ExtTextOut(
		x ,y ,
		ETO_CLIPPED,
		rect,
		txt,
		NULL);
}

CSize ShapeElement::GetTextSize(CString str, CDC *pDC)
{
	return pDC->GetTextExtent( str );
}

void ShapeElement::DrawTextLeft(CRect r, CString txt, CDC *pDC, int marginX)
{
	int x,y;
	CRect rect;
	CSize sz = pDC->GetTextExtent( txt );

	x = r.left + marginX;
	y = ( r.bottom - r.top - sz.cy )/2 + r.top ;
	rect = r;
	rect.right -= m_LineWidth;
	
	pDC->ExtTextOut(
		x ,y ,
		ETO_CLIPPED,
		rect,
		txt,
		NULL);
}

void ShapeElement::SetTempFont(CDC *pDC , LOGFONT lf)
{
	m_TempFont.DeleteObject();
	m_TempFont.CreateFontIndirect( &lf );
	m_pTempFont = pDC->SelectObject( &m_TempFont );
}

void ShapeElement::RestoreFont(CDC *pDC)
{
	pDC->SelectObject( m_pTempFont );
}

void ShapeElement::SetTempPen(CDC *pDC, int width, COLORREF color, int style)
{
	m_TempPen.DeleteObject();
	if( style == -1 )
	{
		style = m_LineStyle;
	}
	m_TempPen.CreatePen( style , width , color );
	m_pTempPen = pDC->SelectObject( &m_TempPen );
}

void ShapeElement::RestorePen(CDC *pDC)
{
	pDC->SelectObject( m_pTempPen );
}

BOOL ShapeElement::In(CPoint pt)
{
	return m_Pos.PtInRect( pt );
}

void ShapeElement::SetTempBrush(CDC *pDC ,COLORREF color, int style)
{
	m_TempBrush.DeleteObject();
	if( style == -1 )
	{
		style = m_FillStyle;
	}
	if( style == 0 )
	{
		m_TempBrush.CreateSolidBrush( color );
	}
	else
	{
		m_TempBrush.CreateHatchBrush( style , color );
	}
	m_pTempBrush = pDC->SelectObject( &m_TempBrush );
}

void ShapeElement::RestoreBrush(CDC *pDC)
{
	pDC->SelectObject( m_pTempBrush );
}

ShapeType ShapeElement::GetType()
{
	return SHAPE_NONE;
}



void ShapeElement::Save(CFile &file ,int &tabnum)
{

}

ShapeElement* ShapeElement::Find(long id)
{
	for(int i = 0 ; i <= m_AllShapes.GetUpperBound() ; i ++)
	{
		ShapeElement *p = m_AllShapes.GetAt( i );
		if( p->m_ID == id )return p;
	}
	return NULL;
}

ShapeNamespace* ShapeElement::GetShapeNamespace()
{
	return NULL;
}

void ShapeElement::WriteTag(CFile &file ,CString str)
{
	file.Write(str,str.GetLength());
}

void ShapeElement::WriteContent(CFile &file, CString str)
{
	file.Write(str,str.GetLength());
}

void ShapeElement::WriteTab(CFile &file, int num)
{
	for( int i = 0 ; i < num ; i ++ )
	{
		file.Write("\t",1);
	}
}

void ShapeElement::WriteEnter(CFile &file)
{
	file.Write("\r\n",2);
}

long ShapeElement::FindClassID(UMLClass *p)
{
	for( int i = 0 ; i <= m_AllShapes.GetUpperBound(); i ++ )
	{
		ShapeElement *pE = m_AllShapes.GetAt( i );
		if( pE->GetType() == SHAPE_CLASS )
		{
			ShapeClass *pC =(ShapeClass*)pE;
			if( pC->m_pClass == p )return pC->m_ID;
		}
	}
	return 0;
}

void ShapeElement::WriteOperation(CFile &file, UMLOperation *pOpe, int &tabnum)
{
		UMLOperation ope = *pOpe;
		CString txt;
		WriteTab( file , tabnum );
		WriteTag( file , "<OPERATION>" );
		WriteEnter( file );
		tabnum ++;
		//name
		txt = "<NAME>";
		txt += ope.name;
		txt += "</NAME>";
		WriteTab( file ,tabnum );
		WriteContent( file ,txt );
		WriteEnter( file );
		//return type
		if( ope.m_ReturnType.m_pType )
		{
			txt.Format("<RETURNTYPE>%d</RETURNTYPE>",FindClassID( ope.m_ReturnType.m_pType ) );
			WriteTab( file , tabnum );
			WriteContent( file , txt );
			WriteEnter( file );
		}
		//visibility
		switch ( ope.m_Visibility )
		{
		case VISIBILITY_PUBLIC:
			txt = "<VISIBILITY>PUBLIC</VISIBILITY>";
			break;
		case VISIBILITY_PRIVATE:
			txt = "<VISIBILITY>PRIVATE</VISIBILITY>";
			break;
		case VISIBILITY_PROTECTED:
			txt = "<VISIBILITY>PROTECTED</VISIBILITY>";
			break;
		default:
			txt = "<VISIBILITY>PACKAGE</VISIBILITY>";
		}
		WriteTab( file , tabnum );
		WriteContent( file , txt );
		WriteEnter( file );
		//param
		for( int j = 0 ; j < ope.m_TypedParameter.GetSize() ; j ++ )
		{
			UMLParameter p = ope.m_TypedParameter.GetAt( j );
			WriteTab( file ,tabnum );
			WriteTag( file , "<PARAMETER>" );
			WriteEnter( file );
			tabnum ++;
			//name
			txt = "<NAME>";
			txt += p.name;
			txt += "</NAME>";
			WriteTab( file ,tabnum );
			WriteContent( file , txt );
			WriteEnter( file );
			//type
			txt.Format("<TYPE>%d</TYPE>",FindClassID( p.m_pType ));
			WriteTab( file ,tabnum );
			WriteContent( file , txt );
			WriteEnter( file );
			//defvalue
			txt = "<DEFVALUE>";
			txt += p.m_DefaultValue;
			txt +="</DEFVALUE>";
			WriteTab( file ,tabnum );
			WriteContent( file , txt );
			WriteEnter( file );
			//dir
			switch( p.m_DirKind )
			{
			case PARAMETER_DIR_IN:
				txt = "<DIR>IN</DIR>";
				break;
			case PARAMETER_DIR_OUT:
				txt = "<DIR>OUT</DIR>";
				break;
			default:
				txt ="<DIR>INOUT</DIR>";
			}
			WriteTab( file ,tabnum );
			WriteContent( file , txt );
			WriteEnter( file );
			//
			tabnum --;
			WriteTab( file ,tabnum );
			WriteTag( file ,"</PARAMETER>" );
			WriteEnter( file );
		}
		tabnum --;
		WriteTab( file , tabnum);
		WriteTag( file , "</OPERATION>" );
		WriteEnter( file );
}

void ShapeElement::WritePos(CFile &file, int &tabnum)
{
	CString txt;
	//pos
	WriteTab( file ,tabnum );
	WriteTag( file , "<POS>" );
	WriteEnter( file );
	tabnum ++;
	//left ,top ,right ,bottom
	txt.Format("<LEFT>%d</LEFT>",m_Pos.left );
	WriteTab( file , tabnum );
	WriteContent( file ,txt );
	WriteEnter( file );

	txt.Format("<TOP>%d</TOP>",m_Pos.top );
	WriteTab( file , tabnum );
	WriteContent( file ,txt );
	WriteEnter( file );

	txt.Format("<RIGHT>%d</RIGHT>",m_Pos.right );
	WriteTab( file , tabnum );
	WriteContent( file ,txt );
	WriteEnter( file );

	txt.Format("<BOTTOM>%d</BOTTOM>",m_Pos.bottom );
	WriteTab( file , tabnum );
	WriteContent( file ,txt );
	WriteEnter( file );

	tabnum --;
	WriteTab( file ,tabnum );
	WriteTag( file , "</POS>" );
	WriteEnter( file );
	//
}

long ShapeElement::FindActivityGraphID(UMLActivityGraph *pr)
{
	for( int i = 0 ; i <= m_AllShapes.GetUpperBound() ;  i ++ )
	{
		ShapeElement *p = m_AllShapes.GetAt( i );
		if( p->GetType() == SHAPE_ACTIVITYDIAGRAM )
		{
			ShapeActivityGraph *pAG = (ShapeActivityGraph*)p;
			if( pAG->m_pActivityGraph == pr )return pAG->m_ID;
		}
	}
	return 0 ;
}

void ShapeElement::WriteParameter(CFile &file, UMLParameter p, int &tabnum)
{
			CString txt;
			WriteTab( file ,tabnum );
			WriteTag( file , "<PARAMETER>" );
			WriteEnter( file );
			tabnum ++;
			//name
			txt = "<NAME>";
			txt += p.name;
			txt += "</NAME>";
			WriteTab( file ,tabnum );
			WriteContent( file , txt );
			WriteEnter( file );
			//type
			txt.Format("<TYPE>%d</TYPE>",FindClassID( p.m_pType ));
			WriteTab( file ,tabnum );
			WriteContent( file , txt );
			WriteEnter( file );
			//defvalue
			txt = "<DEFVALUE>";
			txt += p.m_DefaultValue;
			txt +="</DEFVALUE>";
			WriteTab( file ,tabnum );
			WriteContent( file , txt );
			WriteEnter( file );
			//dir
			switch( p.m_DirKind )
			{
			case PARAMETER_DIR_IN:
				txt = "<DIR>IN</DIR>";
				break;
			case PARAMETER_DIR_OUT:
				txt = "<DIR>OUT</DIR>";
				break;
			default:
				txt ="<DIR>INOUT</DIR>";
			}
			WriteTab( file ,tabnum );
			WriteContent( file , txt );
			WriteEnter( file );
			//
			tabnum --;
			WriteTab( file ,tabnum );
			WriteTag( file ,"</PARAMETER>" );
			WriteEnter( file );
}

void ShapeElement::WriteAttribute(CFile &file, UMLAttribute att, int &tabnum)
{
		CString txt;
		WriteTab( file, tabnum );
		WriteTag( file ,"<ATTRIBUTE>");
		WriteEnter( file );
		tabnum ++;
		//name
		txt = "<NAME>";
		txt += att.name;
		txt += "</NAME>";
		WriteTab( file ,tabnum );
		WriteContent( file ,txt );
		WriteEnter( file );
		//type id
		txt.Format("<TYPE>%d</TYPE>",FindClassID(att.m_pType));
		WriteTab( file ,tabnum);
		WriteContent( file ,txt );
		WriteEnter( file );
		//visibility
		switch( att.m_Visibility )
		{
		case VISIBILITY_PUBLIC:
			txt = "<VISIBILITY>PUBLIC</VISIBILITY>";
			break;
		case VISIBILITY_PRIVATE:
			txt = "<VISIBILITY>PRIVATE</VISIBILITY>";
			break;
		case VISIBILITY_PROTECTED:
			txt = "<VISIBILITY>PROTECTED</VISIBILITY>";
			break;
		case VISIBILITY_PACKAGE:
			txt = "<VISIBILITY>PACKAGE</VISIBILITY>";
			break;
		}
		WriteTab( file ,tabnum);
		WriteContent( file ,txt );
		WriteEnter( file );
		//multiplicity
		txt = "<MULTIPLICITY>";
		txt += att.m_Multiplicity ;
		txt += "</MULTIPLICITY>";
		WriteTab( file ,tabnum);
		WriteContent( file ,txt );
		WriteEnter( file );
		//ini value
		txt = "<INIVALUE>";
		txt += att.m_InitialValue;
		txt += "</INIVALUE>";
		WriteTab( file ,tabnum);
		WriteContent( file ,txt );
		WriteEnter( file );
		//orderkind
		if( att.m_OrderingKind == ORDERING_NONE )
		{
			txt = "<ORDER>NONE</ORDER>";
		}
		else
		{
			txt = "<ORDER>ORDER</ORDER>";
		}
		WriteTab( file ,tabnum);
		WriteContent( file ,txt );
		WriteEnter( file );

		tabnum --;
		WriteTab( file, tabnum );
		WriteTag( file ,"</ATTRIBUTE>");
		WriteEnter( file );
}

BOOL ShapeElement::GetBeUsed()
{
   return beUsed;
}

void ShapeElement::SetBeUsed(BOOL b)
{
   beUsed=b;
}
