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

#include "stdafx.h"
#include "AG_MDA.h"
#include "ShapeClass.h"

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

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

ShapeClass::ShapeClass()
{
	m_ShowAttributes = TRUE;
	m_ShowOperations = TRUE;
	m_Pos.left = 100 ;
	m_Pos.right = 450;
	m_Pos.top = 100 ;
	m_Pos.bottom = 300;

	m_pClass = NULL;
	m_pShapeNamespace = NULL;

	m_pMarkElement = new MarkClass;
}

ShapeClass::~ShapeClass()
{
	//删除活动图
	for( int i = 0; i <= m_pShapeActivityGraphs.GetUpperBound() ; i ++ )
	{
		ShapeActivityGraph *p = m_pShapeActivityGraphs.GetAt( i );
		delete p;
	}
	m_pShapeActivityGraphs.RemoveAll();
	delete m_pClass;
}

void ShapeClass::Draw( CDC *pDC )
{
	CSize classNameSize = GetTextSize( "NNN" , pDC );
	int y = m_Pos.top;
	pDC->Rectangle( m_Pos );


	//绘制类名
	if( m_pClass )
	{
		DrawTextCenter( CRect( m_Pos.left, m_Pos.top , m_Pos.right, m_Pos.top + classNameSize.cy + MARGIN_Y*2 ),
			m_pClass->UMLGeneralizableElement::name,
			pDC,
			m_LineWidth );
	}

	//绘制类名下的第一条线
	SetTempPen( pDC , 1 , m_LineColor );//set templ

	y += MARGIN_Y;
	y += classNameSize.cy;
	y += MARGIN_Y;

	if( y < m_Pos.bottom )
	{
		pDC->MoveTo( m_Pos.left , y );
		pDC->LineTo( m_Pos.right , y );
	}

	RestorePen( pDC );//--restore temp

	LOGFONT ft;
	ft = m_TextFont;
	ft.lfHeight -= 4;
	SetTempFont( pDC , ft );

	//绘制属性
	if(m_pClass && m_ShowAttributes )
	{
		y += MARGIN_Y*2;
		for( int i = 0 ; i < m_pClass->m_Attributes.GetSize() ; i ++)
		{
			UMLAttribute att = m_pClass->m_Attributes.GetAt( i );
			CRect r;
			CString txt;
			y += MARGIN_Y;
			if( att.m_Visibility == VISIBILITY_PUBLIC )
				txt = "+ ";
			else if( att.m_Visibility == VISIBILITY_PRIVATE )
				txt = "- ";
			else if( att.m_Visibility == VISIBILITY_PROTECTED )
				txt = "# ";
			txt += att.name;
			txt += ":";
			if( att.m_pType )
			{
				txt += att.m_pType->UMLGeneralizableElement::name;
			}
			else
			{
				txt +=" ";
			}
			if( att.m_InitialValue.GetLength() )
			{
				txt += " ={";
				txt += att.m_InitialValue;
				txt += "}";
			}
			r.left = m_Pos.left + m_LineWidth;
			r.right = m_Pos.right - m_LineWidth;
			r.top = y ;
			y += GetTextSize( txt , pDC ).cy ;
			r.bottom = y;
			y += MARGIN_Y;
			r.bottom = y;
			DrawTextLeft( r , txt , pDC );
			y += MARGIN_Y;
		}
		y += MARGIN_Y*2;
	}
	else
	{
		y += MARGIN_Y*4;
	}
	//绘制属性的下一条线

	SetTempPen( pDC , 1 , m_LineColor );//set templ

	if( y < m_Pos.bottom )
	{
		pDC->MoveTo( m_Pos.left , y );
		pDC->LineTo( m_Pos.right , y );
	}

	RestorePen( pDC );//--restore temp

	//绘制操作
	if(m_pClass && m_ShowOperations )
	{
		y += MARGIN_Y*2;
		for( int i = 0 ; i < m_pClass->m_Operations.GetSize() ; i ++ )
		{
			UMLOperation ope = m_pClass->m_Operations.GetAt( i );
			CString txt;
			CRect r;
			y += MARGIN_Y;
			if( ope.m_Visibility == VISIBILITY_PUBLIC )
				txt = "+ ";
			else if( ope.m_Visibility == VISIBILITY_PRIVATE )
				txt = "- ";
			else if( ope.m_Visibility == VISIBILITY_PROTECTED )
				txt = "# ";
			else
				txt = "  ";
			txt += ope.name;
			txt += "(";
			for( int j = 0 ; j < ope.m_TypedParameter.GetSize() ; j ++ )
			{
				UMLParameter pa = ope.m_TypedParameter.GetAt( j );
				if ( j ) txt += ",";
				txt +=" ";
				txt += pa.name;
				if( pa.m_pType )
				{
					txt += ":";
					txt += pa.m_pType->UMLGeneralizableElement::name;
				}
			}
			txt += " )";
			if( ope.m_ReturnType.m_pType )
			{
				txt += " : ";
				txt += ope.m_ReturnType.m_pType->UMLGeneralizableElement::name;
			}
			r.left = m_Pos.left + m_LineWidth;
			r.right = m_Pos.right - m_LineWidth;
			r.top = y ;
			y += GetTextSize( txt , pDC ).cy ;
			r.bottom = y;
			y += MARGIN_Y;
			r.bottom = y;
			DrawTextLeft( r , txt , pDC );
			y += MARGIN_Y;
		}
		y += MARGIN_Y*2;
	}

	RestoreFont( pDC );
}

BOOL ShapeClass::In(CPoint pt)
{
	return ShapeElement::In( pt );
}

ShapeType ShapeClass::GetType()
{
	return SHAPE_CLASS;
}

ShapeNamespace* ShapeClass::GetShapeNamespace()
{
	return m_pShapeNamespace;
}

void ShapeClass::Save(CFile &file , int &tabnum)
{
	CString txt;
	WriteTab( file ,tabnum );
	WriteTag( file , "<CLASS>" );
	WriteEnter( file );
	tabnum ++;
	//name
	txt = "<NAME>";
	txt += m_pClass->UMLGeneralizableElement::name;
	txt += "</NAME>";
	WriteTab( file ,tabnum );
	WriteContent( file ,txt );
	WriteEnter( file );
	//id
	txt.Format("<ID>%d</ID>",m_ID);
	WriteTab( file ,tabnum );
	WriteContent( file , txt );
	WriteEnter( file );
	//attribute
	for( int i = 0 ; i < m_pClass->m_Attributes.GetSize();i++ )
	{
		UMLAttribute att = m_pClass->m_Attributes.GetAt( i );
		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 );
	}
	//operation
	for( i = 0 ; i < m_pClass->m_Operations.GetSize() ;i ++ )
	{
		UMLOperation ope;
		ope = m_pClass->m_Operations.GetAt( i );
		WriteOperation( file , &ope , tabnum );
	}
	//activity graph
	for( i = 0 ; i <= m_pShapeActivityGraphs.GetUpperBound() ; i ++ )
	{
		ShapeActivityGraph *pSAG = m_pShapeActivityGraphs.GetAt( i );
		pSAG->Save( file , tabnum );
	}
	//mark
	MarkClass *pMC = (MarkClass*)m_pMarkElement;
	WriteTab( file , tabnum );
	WriteTag( file ,"<MARK>");
	WriteEnter( file );
	tabnum ++;
	//create main
	if( pMC->m_CreateMainFunc )
		txt = "<CREATEMAIN>TRUE</CREATEMAIN>";
	else
		txt = "<CREATEMAIN>FALSE</CREATEMAIN>";
	WriteTab( file , tabnum );
	WriteContent( file ,txt );
	WriteEnter( file );
	//main expression
	if( pMC->m_MainExpression.GetLength() )
	{
		txt ="<EXPRESSION>";
		txt += RemoveEnter( pMC->m_MainExpression );
		txt += "</EXPRESSION>";
		WriteTab( file , tabnum );
		WriteContent( file ,txt );
		WriteEnter( file );
	}
	
	tabnum --;
	WriteTab( file , tabnum );
	WriteTag( file ,"</MARK>");
	WriteEnter( file );
	//
	tabnum --;
	WriteTab( file ,tabnum );
	WriteTag( file , "</CLASS>" );
	WriteEnter( file );
}

CString ShapeClass::RemoveEnter(CString istr)
{
		int i = 0 ; 
	CString str = istr;
	while( i< str.GetLength() )
	{
		if( str.GetAt( i ) == '\r' )
		{
			str.Delete( i );
			continue;
		}
		else if( str.GetAt( i ) == '\n' )
		{
			str.Delete( i );
			continue;
		}
		i ++;
	}
	return str;
}
