// NovellUserSelDlg.cpp : implementation file
//

#include "stdafx.h"
#include "SKOKO.h"
#include "NovellUserSelDlg.h"

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

/////////////////////////////////////////////////////////////////////////////
// CUserTreeCtrl

CUserTreeCtrl::CUserTreeCtrl()
{
}

CUserTreeCtrl::~CUserTreeCtrl()
{
}


BEGIN_MESSAGE_MAP(CUserTreeCtrl, CTreeCtrl)
	//{{AFX_MSG_MAP(CUserTreeCtrl)
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_NOTIFY_REFLECT(NM_KILLFOCUS, OnKillfocus)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CUserTreeCtrl message handlers

void CUserTreeCtrl::OnRButtonDown(UINT nFlags, CPoint point) 
{
  UINT flags;
  HTREEITEM hItem = HitTest(point, &flags);
  if (hItem && (TVHT_ONITEM & flags))
   Select(hItem, TVGN_CARET);

  HTREEITEM hSel = GetSelectedItem();
  if (hSel)
  {
    const CUserTreeNode* pNode = (CUserTreeNode*)GetItemData(hSel);
    if (pNode)
    {
      BGDNet::String className = pNode->baseClass();
      if (className == userClassName)
      {
        CPoint p = point;
        ClientToScreen(&p);
        m_userInfo.ShowInfo(pNode->obj(), this, p);
      }
    }
  }
}

void CUserTreeCtrl::OnRButtonUp(UINT nFlags, CPoint point) 
{
  m_userInfo.HideInfo();
  CTreeCtrl::OnRButtonUp(nFlags, point);
}

void CUserTreeCtrl::OnKillfocus(NMHDR* pNMHDR, LRESULT* pResult) 
{
  m_userInfo.HideInfo();
  *pResult = 0;
}

/////////////////////////////////////////////////////////////////////////////
// CNovellUserSelDlg dialog


CNovellUserSelDlg::CNovellUserSelDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CNovellUserSelDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CNovellUserSelDlg)
	m_sSelectedUser = _T("");
	//}}AFX_DATA_INIT
  m_allowNoOwner = TRUE;
}

void CNovellUserSelDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CNovellUserSelDlg)
	DDX_Control(pDX, IDC_TREE_NDS, m_wndUserTree);
	DDX_Text(pDX, IDC_EDIT_USER, m_sSelectedUser);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CNovellUserSelDlg, CDialog)
	//{{AFX_MSG_MAP(CNovellUserSelDlg)
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_NDS, OnSelchangedTreeNds)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CNovellUserSelDlg message handlers

BOOL CNovellUserSelDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();

  m_wndUserTree.SetImageList(&theApp.m_imageList, TVSIL_NORMAL);

  try
  {
    CWaitCursor wc;

    HTREEITEM hRoot = m_wndUserTree.InsertItem(
      theApp.UserTree().Root()->fullName(),
      theApp.UserTree().Root()->icon(),
      theApp.UserTree().Root()->icon());
    m_wndUserTree.SetItemData(hRoot, (DWORD)theApp.UserTree().Root());
    InsertUsers(hRoot, theApp.UserTree().Root());

    if (m_allowNoOwner)
    {
      HTREEITEM hNoOwner = m_wndUserTree.InsertItem(
        UNKNOWN_OWNER,
        CSKOKOApp::ICON_NO_OWNER,
        CSKOKOApp::ICON_NO_OWNER);
      m_wndUserTree.SetItemData(hNoOwner, 0);
    }
  }
  catch (const BGDNet::Exception& e)
  {
    CString err;
    err.Format(_T("Ошибка сети: %s"), e.what());
    AfxMessageBox(err, MB_ICONSTOP);
  }
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void CNovellUserSelDlg::InsertUsers(
  HTREEITEM hParent,
  const CUserTreeNode* pContainer )
{
  for (int i = 0; i < pContainer->childCount(); ++i)
  {
    const CUserTreeNode* pNode = pContainer->child(i);
    HTREEITEM hItem = m_wndUserTree.InsertItem(
      pNode->fullName(),
      pNode->icon(),
      pNode->icon(),
      hParent);
    m_wndUserTree.SetItemData(hItem, (DWORD)pNode);

    if (pNode->childCount() > 0)
      InsertUsers(hItem, pNode);
  }

  TVSORTCB scb;
  scb.hParent = hParent;
  scb.lParam = 0;
  scb.lpfnCompare = &CompareFunc;
  m_wndUserTree.SortChildrenCB(&scb);
}

void CNovellUserSelDlg::OnSelchangedTreeNds(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

  const CUserTreeNode* pNode = (CUserTreeNode*)m_wndUserTree.GetItemData(
    pNMTreeView->itemNew.hItem);
  if (!pNode)
  {
    GetDlgItem(IDOK)->EnableWindow(TRUE);
    m_sSelectedUser = UNKNOWN_OWNER;
  }
  else
  {
    BGDNet::String className = pNode->baseClass();
    GetDlgItem(IDOK)->EnableWindow(className == userClassName);
    m_sSelectedUser = pNode->dn();
  }
  UpdateData(FALSE);

	*pResult = 0;
}

int CALLBACK CNovellUserSelDlg::CompareFunc(
  LPARAM lParam1,
  LPARAM lParam2, 
  LPARAM lParamSort)
{
  const CUserTreeNode* pNode1 = (CUserTreeNode*)lParam1;
  const CUserTreeNode* pNode2 = (CUserTreeNode*)lParam2;
  if (!pNode1 && !pNode2)
    return 0;
  else if (!pNode1 && pNode2)
    return 1;
  else if (pNode1 && !pNode2)
    return -1;
  else
  {
    if (pNode1->childCount() && !pNode2->childCount())
      return 1;
    else if (!pNode1->childCount() && pNode2->childCount())
      return -1;
    return pNode1->fullName().CompareNoCase(pNode2->fullName());
  }
}

