// SortList1.cpp : implementation file
//

#include "stdafx.h"
#include "SortList.h"

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

/////////////////////////////////////////////////////////////////////////////
// CSortList

CSortList::CSortList()
{
	m_bDragging = FALSE;
	m_bReSort   = false;  //ÿ´ÎÍ϶¯ºó²»ÐèÒªÖØÅÅ
	m_lCheck1    = -1;
	m_lCheck2    = -1;
	m_lCheck3    = -1;
}

CSortList::~CSortList()
{
}


BEGIN_MESSAGE_MAP(CSortList, CListCtrl)
	//{{AFX_MSG_MAP(CSortList)
	ON_WM_LBUTTONUP()
	ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBegindrag)
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSortList message handlers

void CSortList::Init(BOOL bReSort , long lCheck1 , long lCheck2 , long lCheck3)
{
	//ListView_SetExtendedListViewStyle(m_hWnd, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP|LVS_EX_CHECKBOXES);
	this->SetExtendedStyle(LVS_EX_TRACKSELECT|LVS_EX_ONECLICKACTIVATE|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP|LVS_EX_CHECKBOXES);
	m_bReSort = bReSort;  //ÿ´ÎÍ϶¯ºóÊÇ·ñÐèÒªÖØÅÅ
	m_lCheck1  = lCheck1;   //ÿ´Î±ØÑ¡µÄÏîÄ¿
	m_lCheck2  = lCheck2;   //ÿ´Î±ØÑ¡µÄÏîÄ¿
	m_lCheck3  = lCheck3;   //ÿ´Î±ØÑ¡µÄÏîÄ¿
}


void CSortList::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if( m_bDragging )
	{
		//RELEASE THE MOUSE CAPTURE AND END THE DRAGGING
		::ReleaseCapture();
		m_bDragging = FALSE;
		m_pDragImage->DragLeave(GetDesktopWindow());
		m_pDragImage->EndDrag();
		delete m_pDragImage;
		
		//GET THE WINDOW UNDER THE DROP POINT
		CPoint pt(point);
		ClientToScreen(&pt);
		m_pDropWnd = WindowFromPoint(pt);
		
		//DROP THE ITEM ON THE LIST
		if( m_pDropWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)) )
			DropItemOnList();
		CListCtrl::OnLButtonUp(nFlags, point);
		return ;
	}

	if ( m_lCheck1 >=0 ) //ÿ´Î±ØÑ¡
	{
		NoverCheck();  //ÓÀÔ¶±ØÐëµÄÒ»¸ö¡£
	}
	if ( m_bReSort ) //ÖØÅÅ
	{
		ReShowSort();
	}
	
	CListCtrl::OnLButtonUp(nFlags, point);
}

void CSortList::DropItemOnList()
{
        //GET THE DROP INDEX
        m_ptDropPoint.y += 10;
        m_ptDropPoint.x = 0;//allows dropping to right of last column
        m_nDropIndex = this->HitTest(m_ptDropPoint);
        
        //GET INFORMATION ON THE DRAGGED ITEM BY SETTING AN LV_ITEM STRUCTURE
        //AND THEN CALLING GetItem TO FILL IT IN
        TCHAR szLabel[256];
        LV_ITEM lvi;
        ZeroMemory(&lvi, sizeof(LV_ITEM));
        //lvi.mask = LVIF_TEXT | LVIF_IMAGE;
		lvi.mask = LVIF_TEXT;
        lvi.stateMask = LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED;
        lvi.pszText = szLabel;
        lvi.iItem = m_nDragIndex;
        lvi.cchTextMax = 255;
        this->GetItem(&lvi);
        
        //INSERT THE DROPPED ITEM
        if(m_nDropIndex < 0) m_nDropIndex = this->GetItemCount();
        lvi.iItem = m_nDropIndex;
        this->InsertItem(&lvi);
        
        //FILL IN ALL OF THE COLUMNS
        CHeaderCtrl* pHeader = (CHeaderCtrl*)this->GetDlgItem(0);
        int nColumnCount = pHeader->GetItemCount();
        lvi.mask = LVIF_TEXT;
        lvi.iItem = m_nDropIndex;
        //INDEX OF DRAGGED ITEM WILL CHANGE IF ITEM IS DROPPED ABOVE ITSELF
        if(m_nDragIndex > m_nDropIndex) m_nDragIndex++;
        for(int col=1; col < nColumnCount; col++)                                                                                                                     
        {
                _tcscpy(lvi.pszText, (LPCTSTR)(this->GetItemText(m_nDragIndex,
                        col)));
                lvi.iSubItem = col;
                this->SetItem(&lvi);
        }
		BOOL  b = this->GetCheck(m_nDragIndex);
		this->SetCheck( m_nDropIndex , b );
		DWORD dw = this->GetItemData(m_nDragIndex);
		this->SetItemData( m_nDropIndex , dw );

        
        //DELETE THE ITEM THAT WAS DRAGGED FROM ITS ORIGINAL LOCATION
        this->DeleteItem(m_nDragIndex);

		if ( m_bReSort ) //ÖØÅÅ
		{
			ReShowSort();
		}

        //FIX HEADER - it disappears if item was scrolled & dropped;
        pHeader->RedrawWindow();
}

void CSortList::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	//NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	
	
	   *pResult = 0;
	   
	   m_nDragIndex = ((NM_LISTVIEW *)pNMHDR)->iItem;
	   
	   //CREATE A DRAG IMAGE FROM THE CENTER POINT OF THE ITEM IMAGE
	   POINT pt;
	   pt.x = 8;
	   pt.y = 8;
	   m_pDragImage = this->CreateDragImage(m_nDragIndex, &pt);
	   m_pDragImage->BeginDrag(0, CPoint (8, 8));
	   m_pDragImage->DragEnter(
		   GetDesktopWindow(), ((NM_LISTVIEW *)pNMHDR)->ptAction);
	   
	   //SET THE FLAGS INDICATING A DRAG IN PROGRESS
	   m_bDragging = TRUE;
	   m_nDropIndex = -1;
	   m_pDropWnd = this;
	   
	   //CAPTURE ALL MOUSE MESSAGES IN CASE THE USER DRAGS OUTSIDE OF THE VIEW
	   SetCapture();
}

void CSortList::OnMouseMove(UINT nFlags, CPoint point) 
{
	if( m_bDragging )
	{
		m_ptDropPoint = point;
		ClientToScreen(&m_ptDropPoint);
		
		//MOVE THE DRAG IMAGE
		m_pDragImage->DragMove(m_ptDropPoint);
		
		//TEMPORARILY UNLOCK WINDOW UPDATES
		m_pDragImage->DragShowNolock(FALSE);                
		
		//CONVERT THE DROP POINT TO CLIENT CO-ORDIANTES
		m_pDropWnd = WindowFromPoint(m_ptDropPoint);
		m_pDropWnd->ScreenToClient(&m_ptDropPoint);
		
		//SCROLL VIEW IF NECESSARY
		int iOverItem = this->HitTest(m_ptDropPoint);
		int iTopItem = this->GetTopIndex();
		int iBottomItem = iTopItem + this->GetCountPerPage() - 1;
		if (iOverItem == iTopItem && iTopItem != 0)
		{
			this->EnsureVisible(iOverItem - 1, false);
			::UpdateWindow(this->m_hWnd);
		}
		else if (iOverItem == iBottomItem && iBottomItem != (this->GetItemCount() - 1))
		{
			this->EnsureVisible(iOverItem + 1, false);
			::UpdateWindow(this->m_hWnd);
		}
		
		//LOCK WINDOW UPDATES
		m_pDragImage->DragShowNolock(TRUE);
	}

	CListCtrl::OnMouseMove(nFlags, point);
}

void CSortList::ReShowSort()
{
	long lCount = this->GetItemCount();
	TCHAR Buf[32];
	long lIndex = 1;
	for ( int i=0 ; i< lCount ; i++ )
	{
		if ( this->GetCheck(i) )
		{
			_stprintf(Buf , _T("%d") , lIndex  );
			this->SetItemText( i , 0 , Buf );
			lIndex ++;	
		}
		else
			this->SetItemText( i , 0 , _T("  ") );
	}
}

void CSortList::NoverCheck()
{
	if ( m_lCheck1 >=0 ) //ÿ´Î±ØÑ¡
	{
		long lCount=this->GetItemCount();
		for (int i = 0 ; i<lCount ; i++ )
		{
			if ( GetItemData(i) == m_lCheck1 )
				SetCheck(i , true );
			if ( GetItemData(i) == m_lCheck2 )
				SetCheck(i , true );
			if ( GetItemData(i) == m_lCheck3 )
				SetCheck(i , true );
		}
	}
}

void CSortList::CheckAll()
{
	long lCount = GetItemCount();
	for ( int i = 0 ; i<lCount;i++ )
		SetCheck(i,true);
	ReShowSort();
}

void CSortList::ClearAll()
{
	long lCount = GetItemCount();
	for ( int i = 0 ; i<lCount;i++ )
		SetCheck(i,false);
	NoverCheck();
	ReShowSort();
}