// DTreeView.cpp : インプリメンテーション ファイル
//

#include "stdafx.h"
#include "DM2GDED.h"
#include "DTreeView.h"
#include "DM2GDEDDoc.h"
#include "AddImageDlg.h"
#include "AddImageDlg2.h"

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

/////////////////////////////////////////////////////////////////////////////
// CDTreeView

CDTreeView::CDTreeView()
{

}

CDTreeView::~CDTreeView()
{
	InitEdCtx(NULL);
}

BEGIN_MESSAGE_MAP(CDTreeView, CTreeCtrl)
	//{{AFX_MSG_MAP(CDTreeView)
	ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteItem)
	ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
	ON_WM_CREATE()
	ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
	ON_COMMAND(ID_POPUP_ADD_C0, OnPopupAddC0)
	ON_WM_CONTEXTMENU()
	ON_NOTIFY_REFLECT(NM_RETURN, OnReturn)
	ON_WM_GETDLGCODE()
	ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChanged)
	ON_WM_SETFOCUS()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

IMPLEMENT_DYNCREATE(CDTreeView, CTreeCtrl)

/////////////////////////////////////////////////////////////////////////////
// CDTreeView メッセージ ハンドラ

void CDTreeView::OnGDUpdate(UINT nHint, void *pHint)
{
	switch (nHint) {
	case PM_V_RELOAD:
		OnReload();
		break;
	case PM_V_UPDATE_TREE_ITEM:
		{
			CGDEntry *pos = (CGDEntry *)pHint;
			HTREEITEM hItem = FindClass1(*pos, TRUE);
			if (hItem) {
				hItem = FindClass2(hItem, *pos, TRUE);
			}
			break;
		}
	case PM_V_SET_OPT:
		OnSetOpt();
		break;
	case PM_V_UPDATE_ENTRY:
		OnUpdateEntry(*(CGDEntry *)pHint);
		break;
	}
}

void CDTreeView::OnReload()
{
	DeleteAllItems();

	if (!m_pEdCtx) return;

	CGDAT &core = m_pEdCtx->GetGDAT();

	m_nGDRSLT = core.GetGDRSLT();

	HTREEITEM hLv0 = NULL, hLv1 = NULL;
	CGDEntry pos = core.GetHeadPos(), prior = CGDEntry::ERR;
	CString strText;
	while (pos != CGDEntry::ERR) {
		bool fForce = false;

		if (pos.c1() != prior.c1()) {
			strText.Format("%02X %s", 
				0U + pos.c1(),
				(LPCSTR)CGDEntry::GetFriendlyClass1Name(pos.c1())
				);

			fForce = true;
			hLv0 = InsertItem(strText);
			SetItemData(hLv0, new Class1(pos.c1()));
		}

		if (pos.c2() != prior.c2() || fForce) {
			strText.Format("%02X %s", 0U + pos.c2(), (LPCTSTR)FormatClass2Name(pos));

			fForce = true;
			hLv1 = InsertItem(strText, hLv0);
			SetItemData(hLv1, new Class2(pos.c1(), pos.c2()));
		}

		prior = pos;
		pos = core.GetNextPos(pos);
	}
}

void CDTreeView::OnDeleteItem(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	Root *pRoot = reinterpret_cast<Root *>(pNMTreeView->itemOld.lParam);
	if (pRoot) {
		delete pRoot;
	}
	
	*pResult = 0;
}

BOOL CDTreeView::SetItemData(HTREEITEM hItem, Root *pAny)
{
	return CTreeCtrl::SetItemData(hItem, (DWORD)pAny);
}

void CDTreeView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) 
{
	HTREEITEM hItem = GetSelectedItem();
	OnDblclkItem(hItem);

	*pResult = 0;
}

void CDTreeView::OnDblclkItem(HTREEITEM hItem)
{
	if (!m_pEdCtx) return;

	Class2 *p2;
	if (hItem && (p2 = GetItemAsClass2(hItem))) {
		TSelTreeItem more;
		more.lower = p2->lower;
		more.upper = p2->upper;

		m_pEdCtx->DispatchGDUpdate(PM_V_SEL_TREE_ITEM, &more);
	}
}

int CDTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	LOGFONT lf;
	ZeroMemory(&lf, sizeof(lf));
	GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
	lf.lfHeight = MulDiv(lf.lfHeight, 3, 2);
	lf.lfCharSet = FIXED_PITCH;
	m_font.DeleteObject();
	m_font.CreateFontIndirect(&lf);

	SetFont(&m_font);
	
	return 0;
}

void CDTreeView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	CPoint point;
	GetCursorPos(&point);

	ShowContextMenu(point, GetSelectedItem());
	
	*pResult = 0;
}

void CDTreeView::OnPopupAddC0() 
{
	CGDEntry pos(0,0,0,0,0,0);
	{
		HTREEITEM hItem = GetNextItem(NULL, TVGN_CARET);
		Class1 *p1 = GetItemAsClass1(hItem);
		if (p1) {
			pos = p1->lower;
		} else {
			Class2 *p2 = GetItemAsClass2(hItem);
			if (p2) {
				pos = p2->lower;
			}
		}
	}

	CAddImageDlg2 wndDlg(this);
	wndDlg.InitAddClass2(pos);
	int r = wndDlg.DoModal();
	if (r != IDOK)
		return;
	pos = wndDlg.GetEntryPos();

	HTREEITEM hItem = FindClass1(pos, TRUE);
	if (hItem) {
		hItem = FindClass2(hItem, pos, TRUE);
		if (hItem) {
			Select(hItem, TVGN_CARET);
		}
	}
}

HTREEITEM CDTreeView::FindClass1(const CGDEntry &pos, BOOL fAdd)
{
	HTREEITEM hParent = NULL;
	HTREEITEM hItem = GetRootItem();
	HTREEITEM hAfter = TVI_FIRST;
	while (hItem) {
		Class1 *p1 = GetItemAsClass1(hItem);
		if (p1) {
			if (p1->lower.c1() == pos.c1()) {
				return hItem;
			}
			if (pos.c1() < p1->lower.c1())
				break;
		}

		hAfter = hItem;
		hItem = GetNextSiblingItem(hItem);
	}
	if (!fAdd)
		return NULL;
	CString strText;
	strText.Format("%02X %s", 
		0U + pos.c1(),
		(LPCSTR)CGDEntry::GetFriendlyClass1Name(pos.c1())
		);
	HTREEITEM hNew = InsertItem(strText, hParent, hAfter);
	SetItemData(hNew, new Class1(pos.c1())); 
	return hNew;
}

HTREEITEM CDTreeView::FindClass2(HTREEITEM hParent, const CGDEntry &pos, BOOL fAdd)
{
	HTREEITEM hItem = GetChildItem(hParent);
	HTREEITEM hAfter = TVI_FIRST;
	while (hItem) {
		Class2 *p2 = GetItemAsClass2(hItem);
		if (p2) {
			if (p2->lower.c2() == pos.c2()) {
				return hItem;
			}
			if (pos.c2() < p2->lower.c2())
				break;
		}

		hAfter = hItem;
		hItem = GetNextSiblingItem(hItem);
	}
	if (!fAdd)
		return NULL;
	CString strText;
	strText.Format("%02X", 0U + pos.c2());
	HTREEITEM hNew = InsertItem(strText, hParent, hAfter);
	SetItemData(hNew, new Class2(pos.c1(), pos.c2())); 
	return hNew;
}

void CDTreeView::OnContextMenu(CWnd* pWnd, CPoint point) 
{
	if (point.x < 0) {
		point.x = point.y = 0;
		ClientToScreen(&point);
	}

	ShowContextMenu(point, GetSelectedItem());
}

void CDTreeView::ShowContextMenu(CPoint point, HTREEITEM hItem)
{
	CMenu m;
	m.LoadMenu(IDR_TREECLS);
	CMenu *p = m.GetSubMenu(0);
	p->TrackPopupMenu(TPM_RIGHTBUTTON, point.x, point.y, this);
}

void CDTreeView::OnReturn(NMHDR* pNMHDR, LRESULT* pResult) 
{
	GetParentFrame()->OnCmdMsg(ID_NEXT_PANE, 0, NULL, NULL);

//	GetParentFrame()->OnCmdMsg(ID_CTRL_GRIDVIEW, 0, NULL, NULL);

//	HTREEITEM hItem = GetSelectedItem();
//	OnDblclkItem(hItem);
//	
	*pResult = TRUE;
}

UINT CDTreeView::OnGetDlgCode() 
{
	return CTreeCtrl::OnGetDlgCode() | DLGC_WANTALLKEYS;
}

void CDTreeView::OnSetOpt()
{
	if (!m_pEdCtx) return;

	CGDEdOpt aOptNew;
	m_pEdCtx->GetOpts(aOptNew);

	if (false
		|| m_aOpt.m_inlang != aOptNew.m_inlang
		|| m_aOpt.m_cnlang != aOptNew.m_cnlang
	) {
		m_ilspCnlang = CILSp::GetCnlang(aOptNew.m_cnlang);
		m_ilspInlang = CILSp::GetInlang(aOptNew.m_inlang);

		m_aOpt.m_inlang = aOptNew.m_inlang;
		m_aOpt.m_cnlang = aOptNew.m_cnlang;

		CWaitCursor wc;
		OnUpdateTreeItemName();
	}
}

void CDTreeView::OnUpdateTreeItemName()
{
	CString strText;

	HTREEITEM hLv1 = GetRootItem();
	while (hLv1) {
		HTREEITEM hLv2 = GetChildItem(hLv1);
		while (hLv2) {
			//
			Class2 *p2 = GetItemAsClass2(hLv2);
			if (p2) {
				CGDEntry pos = p2->lower;
				strText.Format("%02X %s", 0U + pos.c2(), (LPCTSTR)FormatClass2Name(pos));

				SetItemText(hLv2, strText);
			}
			//
			hLv2 = GetNextSiblingItem(hLv2);
		}
		hLv1 = GetNextSiblingItem(hLv1);
	}
}

void CDTreeView::OnUpdateEntry(const CGDEntry &pos)
{
	HTREEITEM hItem = FindClass1(pos, TRUE);
	if (hItem) {
		hItem = FindClass2(hItem, pos, TRUE);
		if (hItem) {
			Class2 *p2 = GetItemAsClass2(hItem);
			if (p2) {
				CString strText;
				CGDEntry pos = p2->lower;
				strText.Format("%02X %s", 0U + pos.c2(), (LPCTSTR)FormatClass2Name(pos));

				SetItemText(hItem, strText);
			}
		}
	}
}

void CDTreeView::OnSelChanged(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	HTREEITEM hItem = pNMTreeView->itemNew.hItem;
	OnDblclkItem(hItem);
	
	*pResult = 0;
}

void CDTreeView::OnSetFocus(CWnd* pOldWnd) 
{
	CTreeCtrl::OnSetFocus(pOldWnd);
	
	CCmdTarget *p;
	if (p = GetParentFrame()) {
		p->OnCmdMsg(ID_UPDATE_CURRENT_PANE, 0, NULL, NULL);
	}
	
}
