// ClassInfoDlg_Global.cpp : implementation file
//

#include "stdafx.h"
#include "ClassInfoDlg_Global.h"
#include "ProjectDoc.h"
#include "XmlClassInfo.h"
#include "XmlProject.h"
#include "MemDC.h"
#include "GuiDefs.h"

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



/////////////////////////////////////////////////////////////////////////////
// CClassInfoDlg_Global dialog


CClassInfoDlg_Global::CClassInfoDlg_Global(CWnd* pParent /*=NULL*/)
	: CPropertyEditorDlg(CClassInfoDlg_Global::IDD, pParent),
	classInfo_(NULL),
	initialized_(false)
{
	//{{AFX_DATA_INIT(CClassInfoDlg_Global)
	//}}AFX_DATA_INIT
}


void CClassInfoDlg_Global::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CClassInfoDlg_Global)
	DDX_Control(pDX, IDC_TXT_CLASS_CONTAINER_CAPTION, txtContainerCaption_);
	DDX_Control(pDX, IDC_CHK_INHERIT, chkInherit_);
	DDX_Control(pDX, IDC_CBO_CLASS_LIST, cboClassList_);
	DDX_Control(pDX, IDC_TXT_CLASS_DESCRIPTION, txtClassDescription_);
	DDX_Control(pDX, IDC_TXT_CLASS_CAPTION, txtClassCaption_);
	DDX_Control(pDX, IDC_TXT_CLASS_NAME, txtClassName_);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CClassInfoDlg_Global, CPropertyEditorDlg)
	//{{AFX_MSG_MAP(CClassInfoDlg_Global)
	ON_EN_KILLFOCUS(IDC_TXT_CLASSNAME, OnKillFocusTxtClassname)
	ON_CBN_SELCHANGE(IDC_CBO_CLASS_LIST, OnSelChangeCboClassList)
	ON_BN_CLICKED(IDC_CHK_INHERIT, OnChkInherit)
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	ON_WM_CTLCOLOR()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CClassInfoDlg_Global message handlers
void CClassInfoDlg_Global::StoreData()
{
	if (classInfo_ == NULL)
		return;

	cmString tmp;

	txtClassName_.GetWindowText(tmp);
	classInfo_->SetName(tmp);

	txtClassCaption_.GetWindowText(tmp);
	classInfo_->SetCaption(tmp);

	txtContainerCaption_.GetWindowText(tmp);
	classInfo_->SetContainerCaption(tmp);

	txtClassDescription_.GetWindowText(tmp);
	classInfo_->SetDescription(tmp);

	CXmlClassInfo* rootClass;
	CXmlClassInfo* newLinkClass;
	CXmlClassInfo* oldLinkClass;
	cmString selClassName;

	rootClass = GetDocument()->GetProject()->GetRootElement();

	// get old link class and mark it as "unlocked"
	//
	oldLinkClass = dynamic_cast<CXmlClassInfo*>(rootClass->GetMember(classInfo_->GetInherithClassId(), enDataType_Class));
	if (oldLinkClass)
		oldLinkClass->SetLockedByInheritance(false);

	// get new link class and mark it as "locked"
	//
	if (cboClassList_.GetCurSel() != CB_ERR)
		cboClassList_.GetLBText(cboClassList_.GetCurSel(), selClassName);

	newLinkClass = dynamic_cast<CXmlClassInfo*>(rootClass->GetMember(selClassName, enDataType_Class, true));
	
	if (newLinkClass) {
		classInfo_->SetInherithClassId(newLinkClass->GetId());
		newLinkClass->SetLockedByInheritance(true);
	}

	classInfo_->SetDefinitionInheritance(chkInherit_.GetCheck() == TRUE);
}

void CClassInfoDlg_Global::SetData(CXmlBaseElement* element)
{
		
	classInfo_ = dynamic_cast<CXmlClassInfo*>(element);
	assert(classInfo_);
	if (classInfo_ == NULL)
		return;

	txtClassName_.SetWindowText(classInfo_->GetName());
	txtContainerCaption_.SetWindowText(classInfo_->GetContainerCaption());
	txtClassCaption_.SetWindowText(classInfo_->GetCaption());
	txtClassDescription_.SetWindowText(classInfo_->GetDescription());

	chkInherit_.SetCheck(classInfo_->GetDefinitionInheritance());

	// only leaf classes can link to other classes
	//
	if (classInfo_->CanInheritDefinition()) {
		
		// create class list
		//
		ClassMemberMap classList;
		ClassMemberMap::iterator it;
		CProjectDoc* doc;
		CXmlClassInfo* rootElement;
		CXmlClassInfo* classInfo;
		CXmlBaseElement* tmpElement;
		wstring selName;

		cboClassList_.ResetContent();
		doc = GetDocument();
		if (doc) {
			rootElement = doc->GetProject()->GetRootElement();

			rootElement->GetMembers(classList, enDataType_Class);

			for (it = classList.begin(); it != classList.end(); it++) {
				classInfo = dynamic_cast<CXmlClassInfo*>(it->second);
				
				// if classInfo contains the currently edited class, classInfo is not 
				// inserted into the list just to avoid infinite nested classes
				//
				tmpElement = classInfo->GetMemberById(classInfo_->GetId());

				if (tmpElement == NULL && classInfo->GetId() != element->GetId() && !classInfo->GetDefinitionInheritance()) {
					cboClassList_.AddString(classInfo->GetName());
				
					if (classInfo->GetId() == classInfo_->GetInherithClassId())
						selName = classInfo->GetName();
				}
			}
			
			if (selName != _T(""))
				cboClassList_.SelectString(-1, selName.c_str());
		}
	}

	UpdateControls();
}

void CClassInfoDlg_Global::SetClassName(const wstring& name)
{
	txtClassName_.SetWindowText(name.c_str());
}

void CClassInfoDlg_Global::OnOK()
{
}

void CClassInfoDlg_Global::OnCancel()
{
}

void CClassInfoDlg_Global::OnKillFocusTxtClassname() 
{
	cmString newClassName;

	txtClassName_.GetWindowText(newClassName);
	
	// TODO: validate class name
	//
	
	if (classInfo_) {
		classInfo_->SetName(newClassName);

		UpdateAllViews(enUpdateViewReason_ItemNameChanged);
	}
}

void CClassInfoDlg_Global::OnDataUpdate()
{
	txtClassName_.SetWindowText(classInfo_->GetName());
}

void CClassInfoDlg_Global::UpdateControls()
{
	cboClassList_.EnableWindow(classInfo_->CanInheritDefinition() && chkInherit_.GetCheck());
	chkInherit_.EnableWindow(classInfo_->CanInheritDefinition());
}

void CClassInfoDlg_Global::OnSelChangeCboClassList() 
{
	StoreData();
	UpdateAllViews(enUpdateViewReason_ItemChanged);
}

void CClassInfoDlg_Global::OnChkInherit() 
{
	StoreData();
	UpdateControls();
	UpdateAllViews(enUpdateViewReason_ItemChanged);
}

void CClassInfoDlg_Global::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	UpdateWindowSize();	
}

void CClassInfoDlg_Global::UpdateWindowSize()
{
	if (!initialized_)
		return;

	CRect rc;
	CRect txtRect;
	int itemWidth;

	GetClientRect(rc);

	txtClassName_.GetWindowRect(txtRect);
	ScreenToClient(txtRect);
	itemWidth = rc.Width() - BORDER - txtRect.left;
	txtClassName_.SetWindowPos(&CWnd::wndTop, 0, 0, itemWidth, txtRect.Height(), SWP_SHOWWINDOW | SWP_NOMOVE);

	txtClassCaption_.GetWindowRect(txtRect);
	ScreenToClient(txtRect);
	itemWidth = rc.Width() - BORDER - txtRect.left;
	txtClassCaption_.SetWindowPos(&CWnd::wndTop, 0, 0, itemWidth, txtRect.Height(), SWP_SHOWWINDOW | SWP_NOMOVE);

	txtContainerCaption_.GetWindowRect(txtRect);
	ScreenToClient(txtRect);
	itemWidth = rc.Width() - BORDER - txtRect.left;
	txtContainerCaption_.SetWindowPos(&CWnd::wndTop, 0, 0, itemWidth, txtRect.Height(), SWP_SHOWWINDOW | SWP_NOMOVE);

	txtClassDescription_.GetWindowRect(txtRect);
	ScreenToClient(txtRect);
	itemWidth = rc.Width() - BORDER - txtRect.left;
	txtClassDescription_.SetWindowPos(&CWnd::wndTop, 0, 0, itemWidth, txtRect.Height(), SWP_SHOWWINDOW | SWP_NOMOVE);

	cboClassList_.GetWindowRect(txtRect);
	ScreenToClient(txtRect);
	itemWidth = rc.Width() - BORDER - txtRect.left;
	cboClassList_.SetWindowPos(&CWnd::wndTop, 0, 0, itemWidth, txtRect.Height(), SWP_SHOWWINDOW | SWP_NOMOVE);
}

BOOL CClassInfoDlg_Global::OnInitDialog() 
{
	CPropertyEditorDlg::OnInitDialog();

	initialized_ = true;

	UpdateWindowSize();

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}


HBRUSH CClassInfoDlg_Global::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	
	if (nCtlColor == CTLCOLOR_STATIC) {
		static CBrush b;

		if(b.GetSafeHandle() == NULL)
			b.CreateSolidBrush(DIALOG_BACK_COLOR);

		pDC->SetBkMode(OPAQUE);
		pDC->SetBkColor(DIALOG_BACK_COLOR);
		return b;

	}
	
	return hbr;
}

BOOL CClassInfoDlg_Global::OnEraseBkgnd(CDC* pDC) 
{
	return TRUE;
}

void CClassInfoDlg_Global::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	CMemDC memDC(&dc);
	CRect rc;

	GetClientRect(rc);

	memDC.FillSolidRect(rc, DIALOG_BACK_COLOR);
}
