// CaplFindInTableDlg.cpp : implementation file
//

#include "stdafx.h"
#include "apl_gui.h"
#include "resource.h"
#include "aplFindInTableDlg.h"

static CaplFindInTableDlg st_CaplFindInTableDlg; 

CaplMap st_map_CaplFindInTableDlg_hook;


void aplInstallFindInTable(CWnd *ctrl)  // Добавляетдля окна обработчик, который по CTRL+F отображает диалог поиска (aplShowFindInCtrl)
{
	if(0==ctrl) return;
	if(0==ctrl->m_hWnd)return;

	CaplFindInTableDlg::Install(ctrl);
}

void aplDeInstallFindInTable(CWnd *ctrl)
{
	if(0==ctrl) return;
	CaplFindInTableDlg::DeInstall(ctrl);
	st_CaplFindInTableDlg.Hide();
}

void aplShowFindInTable(CWnd *ctrl) 
{
	if(0==ctrl) return;
	if(0==ctrl->m_hWnd)return;

	st_CaplFindInTableDlg.Show(ctrl);
}

// CaplFindInTableDlg dialog

IMPLEMENT_DYNAMIC(CaplFindInTableDlg, CaplTranslateDialog)

CaplFindInTableDlg::CaplFindInTableDlg(CWnd* pParent /*=NULL*/) :
//	: CaplTranslateDialog(CaplFindInTableDlg::IDD, pParent)
m_bFindWholeString(FALSE)
{

}

CaplFindInTableDlg::~CaplFindInTableDlg()
{
}

void CaplFindInTableDlg::DoDataExchange(CDataExchange* pDX)
{
	CaplTranslateDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_FIND_FIRST, m_btnFindFirst);
	DDX_Control(pDX, IDC_FIND_NEXT, m_btnFindNext);
	DDX_Control(pDX, IDC_FIND_PREV, m_btnFindPrev);
	DDX_Control(pDX, IDC_TEXT, m_text_ctrl);
	DDX_Control(pDX, IDC_COLUMN_NAME, m_colums_box);
	DDX_Check(pDX, IDC_CHECK_FIND_WHOLE_STRING, m_bFindWholeString);
}


BEGIN_MESSAGE_MAP(CaplFindInTableDlg, CaplTranslateDialog)
	ON_BN_CLICKED(IDC_FIND_FIRST, &CaplFindInTableDlg::OnBnClickedFindFirst)
	ON_BN_CLICKED(IDC_FIND_NEXT, &CaplFindInTableDlg::OnBnClickedFindNext)
	ON_BN_CLICKED(IDC_FIND_PREV, &CaplFindInTableDlg::OnBnClickedFindPrev)
	ON_WM_CLOSE()
END_MESSAGE_MAP()


// CaplFindInTableDlg message handlers

void CaplFindInTableDlg::OnBnClickedFindFirst(){FindNextItem(0);}
void CaplFindInTableDlg::OnBnClickedFindNext() {FindNextItem(1);}
void CaplFindInTableDlg::OnBnClickedFindPrev() {FindNextItem(-1);}

void CaplFindInTableDlg::FindNextItem(int delta)
{
	UpdateData();

	if(0==m_treelist && 0==m_list)   return;
	
	if(0!=m_treelist)
	{
		if(!IsWindow(m_treelist->m_hWnd))return;
	}
	if(0!=m_list)
	{
		if(!IsWindow(m_list->m_hWnd))return;
	}

	CString text;
	m_text_ctrl.GetWindowText(text);
	if(text==_T("")){AfxMessageBox(APL_T("Не задана подстрока!"),MB_OK|MB_ICONWARNING);m_text_ctrl.SetFocus(); return;}
	text.MakeLower();

	int col=m_colums_box.GetCurSel()-1;
	m_colums_box.GetLBText(m_colums_box.GetCurSel(),m_prev_column);

	if(0!=m_treelist) CaplFindInTableDlgBar::FindNextTreeListItem(m_treelist, text,delta, col, m_bFindWholeString?true:false);
	else if(0!=m_list) CaplFindInTableDlgBar::FindNextListItem(m_list, text, delta, col, m_bFindWholeString ? true : false);
}

void CaplFindInTableDlg::Hide()
{
	if(0==m_hWnd) return;
	OnClose();
}

void CaplFindInTableDlg::Show(CWnd *wnd4find)
{
	if(0==wnd4find) return;
	if(0==m_hWnd)
	{
		CaplSetResourceHandle setres(module_inst);
		if(!Create(IDD_FIND_IN_TABLE,0))  return;
		UpdateData(FALSE);
		m_btnFindFirst.SetFlat(FALSE);
		m_btnFindNext.SetFlat(FALSE);
		m_btnFindPrev.SetFlat(FALSE);
		m_btnFindFirst.SetIcon(GetAplTableIco((APL_TABLE_FIND)));
		m_btnFindNext.SetIcon(GetAplTableIco((APL_TABLE_BOTTOM)));
		m_btnFindPrev.SetIcon(GetAplTableIco((APL_TABLE_TOP)));
	}

	if(wnd4find->IsKindOf(RUNTIME_CLASS(CaplTreeListCtrlView)))
	{
		CaplTreeListCtrlWithToolTip *tr_wtt=&(((CaplTreeListCtrlView*)wnd4find)->m_tree);
		wnd4find=tr_wtt;
	}

	if(wnd4find->IsKindOf(RUNTIME_CLASS(CaplTreeListCtrl))) m_treelist=(CaplTreeListCtrl*)wnd4find;
	else if(wnd4find->IsKindOf(RUNTIME_CLASS(CaplTreeListCtrlView))) m_treelist=&(((CaplTreeListCtrlView*)wnd4find)->m_tree);
	else if(wnd4find->IsKindOf(RUNTIME_CLASS(CListCtrl))) m_list=(CListCtrl*)wnd4find;
	else if(wnd4find->IsKindOf(RUNTIME_CLASS(CListView))) m_list=&(((CListView*)wnd4find)->GetListCtrl());
	else
	{
		#ifdef _DEBUG
				AfxMessageBox(_T("Неверный вызов CaplFindInTableDlg::Show.  Передан не ListCtrl или TreeCtrl"),MB_OK|MB_ICONSTOP);
		#endif
		return; 
	}
	CHeaderCtrl *header=0;
	if(0!=m_treelist)header=&m_treelist->m_wndHeader;
	else if(m_list!=0) header=m_list->GetHeaderCtrl();
	if(0==header) return;
	CaplFindInTableDlgBar::UpdateColumnsList(header,&m_colums_box);
	if(m_prev_column!=_T("")) m_colums_box.SelectString(-1,m_prev_column);

	RECT rect,rect1;
	wnd4find->GetClientRect(&rect);
	wnd4find->ClientToScreen(&rect);
	GetWindowRect(&rect1);
	rect.left=rect.right-(rect1.right-rect1.left);
	rect.bottom=rect.top+(rect1.bottom-rect1.top);
	MoveWindow(&rect);

	ShowWindow(SW_SHOW);

	//m_text_ctrl.SetFocus();
}

void CaplFindInTableDlg::OnClose()
{
	// TODO: Add your message handler code here and/or call default
	UpdateData();

	CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0
	if(0!=app) app->WriteProfileInt(_T("Settings"), _T("FindWholeString"), m_bFindWholeString ? 1 : 0);

	ShowWindow(SW_HIDE);

	if(0!=m_treelist && IsWindow(m_treelist->m_hWnd)) m_treelist->SetFocus();
	else if(0!=m_list  && IsWindow(m_list->m_hWnd)) m_list->SetFocus();
	//CaplTranslateDialog::OnClose();
}


HHOOK CaplFindInTableDlg_HookProc_hk =0;
CaplMap CaplFindInTableDlg_map_wnd;  // Считаем что таких окон будет десятки

LRESULT  CALLBACK CaplFindInTableDlg_HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	//MessageBox(NULL,"Hook","Hook",MB_OK);

	if(HC_ACTION ==nCode)
	{
		char c=(char)LOWORD(wParam);
		if(c==_T('f') || c==_T('F')|| c==_T('а') || c==_T('А'))
		{
			if (GetKeyState(VK_CONTROL) < 0)
			{
				HWND hWnd=GetFocus();
				if(0!=hWnd)
				{
					if(CaplFindInTableDlg_map_wnd.QFindByIn((long)hWnd)>=0)
					{
						CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
						st_CaplFindInTableDlg.Show(pWnd);
						return 0;
					}
				}
			}
		}
	}
	return CallNextHookEx(CaplFindInTableDlg_HookProc_hk, nCode, wParam, lParam);
}



void CaplFindInTableDlg::Install (CWnd *wnd4find)
{

	//SubclassWindow(wnd4find->m_hWnd);
	if(0==CaplFindInTableDlg_HookProc_hk) CaplFindInTableDlg_HookProc_hk = SetWindowsHookEx(WH_KEYBOARD,&CaplFindInTableDlg_HookProc, 0, GetCurrentThreadId());
	CaplFindInTableDlg_map_wnd.Add((long)(wnd4find->m_hWnd),0);

	if(wnd4find->IsKindOf(RUNTIME_CLASS(CaplTreeListCtrlView)))
	{
		CaplFindInTableDlg_map_wnd.Add((long)((((CaplTreeListCtrlView*)wnd4find)->m_tree).m_hWnd),0);
	}
	else if(wnd4find->IsKindOf(RUNTIME_CLASS(CListView)))
	{
		CaplFindInTableDlg_map_wnd.Add((long)(((CListView*)wnd4find)->GetListCtrl().m_hWnd),0);
	}
}

void CaplFindInTableDlg::DeInstall (CWnd *wnd4find)
{
	if(0==wnd4find) return;

	int i=CaplFindInTableDlg_map_wnd.FindByIn((long)(wnd4find->m_hWnd));
	if(i>=0)CaplFindInTableDlg_map_wnd.Remove(i);

	if(wnd4find->IsKindOf(RUNTIME_CLASS(CaplTreeListCtrlView)))
	{
		int i=CaplFindInTableDlg_map_wnd.FindByIn((long)((((CaplTreeListCtrlView*)wnd4find)->m_tree).m_hWnd));
		if(i>=0)CaplFindInTableDlg_map_wnd.Remove(i);
	}
	else if(wnd4find->IsKindOf(RUNTIME_CLASS(CListView)))
	{
		int i=CaplFindInTableDlg_map_wnd.FindByIn((long)(((CListView*)wnd4find)->GetListCtrl().m_hWnd));
		if(i>=0)CaplFindInTableDlg_map_wnd.Remove(i);
	}
}


WNDPROC CaplFindInTableDlg::st_DefEditProc=0; // Исходим из ттго, что экземпляр каласса всегда будет только один
WNDPROC CaplFindInTableDlg::st_DefProcComboColumn=0; 
WNDPROC CaplFindInTableDlg::st_DefProcbtnFindFirst=0; 
WNDPROC CaplFindInTableDlg::st_DefProcbtnFindNext=0; 
WNDPROC CaplFindInTableDlg::st_DefProcbtnFindPrev=0; 


LRESULT CaplFindInTableDlg::UniversalEditKeyProc(WNDPROC proc, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if(0==proc) return 0;
	if(uMsg==WM_KEYDOWN)
	{
		if(VK_F3==wParam)
		{
			if (GetKeyState(VK_LSHIFT)<0 || GetKeyState(VK_LSHIFT)<0 )
				st_CaplFindInTableDlg.OnBnClickedFindPrev();
			else st_CaplFindInTableDlg.OnBnClickedFindNext();
			return 0;
		}
	}
	return CallWindowProc(proc, hwnd, uMsg, wParam, lParam);
}


LRESULT CaplFindInTableDlg::EditKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return UniversalEditKeyProc(st_DefEditProc, hwnd, uMsg, wParam, lParam);
}
LRESULT CaplFindInTableDlg::btnFindFirstProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return UniversalEditKeyProc(st_DefProcbtnFindFirst, hwnd, uMsg, wParam, lParam);
}
LRESULT CaplFindInTableDlg::btnFindNextKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return UniversalEditKeyProc(st_DefProcbtnFindNext, hwnd, uMsg, wParam, lParam);
}
LRESULT CaplFindInTableDlg::btnFindPrevKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return UniversalEditKeyProc(st_DefProcbtnFindPrev, hwnd, uMsg, wParam, lParam);
}
LRESULT CaplFindInTableDlg::ComboColumnKeyProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	return UniversalEditKeyProc(st_DefProcComboColumn, hwnd, uMsg, wParam, lParam);
}

BOOL CaplFindInTableDlg::OnInitDialog()
{
	CaplTranslateDialog::OnInitDialog();
	st_DefEditProc=(WNDPROC)SetWindowLong(m_text_ctrl.m_hWnd, GWL_WNDPROC, (long) (&(CaplFindInTableDlg::EditKeyProc)));
	st_DefProcComboColumn=(WNDPROC)SetWindowLong(m_colums_box.m_hWnd, GWL_WNDPROC, (long) (&(CaplFindInTableDlg::ComboColumnKeyProc)));
	st_DefProcbtnFindFirst=(WNDPROC)SetWindowLong(m_btnFindFirst.m_hWnd, GWL_WNDPROC, (long) (&(CaplFindInTableDlg::btnFindFirstProc)));
	st_DefProcbtnFindNext=(WNDPROC)SetWindowLong(m_btnFindNext.m_hWnd, GWL_WNDPROC, (long) (&(CaplFindInTableDlg::btnFindNextKeyProc))); 
	st_DefProcbtnFindPrev=(WNDPROC)SetWindowLong(m_btnFindPrev.m_hWnd, GWL_WNDPROC, (long) (&(CaplFindInTableDlg::btnFindPrevKeyProc)));

	m_bFindWholeString =0;
	CWinApp *app=AfxGetApp(); // При вызове из ActiveX возвращает 0
	if(0!=app) m_bFindWholeString=app->GetProfileInt(_T("Settings"), _T("FindWholeString"), 0);

	UpdateData(FALSE);

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

