// MyListCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "supervis.h"
#include "MyListCtrl.h"

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

/////////////////////////////////////////////////////////////////////////////
// CMyListCtrl

CMyListCtrl::CMyListCtrl()
{
	nSortedCol = -1; 
    bSortAscending = TRUE; 
}

CMyListCtrl::~CMyListCtrl()
{
}


BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
	//{{AFX_MSG_MAP(CMyListCtrl)
	ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
	ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)
	ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked) 
	ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyListCtrl message handlers

void CMyListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// Get the current mouse location and convert it to client
	// coordinates.
	DWORD pos = GetMessagePos();

	CPoint pt(LOWORD(pos), HIWORD(pos));
	ScreenToClient(&pt);

	// Get indexes of the first and last visible items in listview
	// control.
	int index = GetTopIndex();

	int last_visible_index = index + GetCountPerPage();

	if (last_visible_index > GetItemCount())
		last_visible_index = GetItemCount();

	// Loop until number visible items has been reached.

	while (index <= last_visible_index)
	{

		// Get the bounding rectangle of an item. If the mouse

		// location is within the bounding rectangle of the item,

		// you know you have found the item that was being clicked.

		CRect r;
		GetItemRect(index, &r, LVIR_BOUNDS);


		if (r.PtInRect(pt))
		{
			UINT flag = LVIS_SELECTED | LVIS_FOCUSED;

			SetItemState(index, flag, flag);
			break;

		}

		// Get the next item in listview control.
		index++;
	}

	
	*pResult = 0;
}

void CMyListCtrl::OnRclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	
	// Get the current mouse location and convert it to client
	// coordinates.
	DWORD pos = GetMessagePos();

	CPoint pt(LOWORD(pos), HIWORD(pos));
	ScreenToClient(&pt);

	// Get indexes of the first and last visible items in listview
	// control.
	int index = GetTopIndex();

	int last_visible_index = index + GetCountPerPage();

	if (last_visible_index > GetItemCount())
		last_visible_index = GetItemCount();

	// Loop until number visible items has been reached.

	while (index <= last_visible_index)
	{

		// Get the bounding rectangle of an item. If the mouse

		// location is within the bounding rectangle of the item,

		// you know you have found the item that was being clicked.

		CRect r;
		GetItemRect(index, &r, LVIR_BOUNDS);


		if (r.PtInRect(pt))
		{
			
			//Select item
			UINT flag = LVIS_SELECTED | LVIS_FOCUSED;

			SetItemState(index, flag, flag);


			//Show PopUp Menu
			CMenu menu;
			VERIFY(menu.LoadMenu(IDR_MENU1));
			CMenu* pPopup = menu.GetSubMenu(0);
			
			//Modify the menu with the ressource name. The Command is handled in CPropertySheet::OnCmdMsg.
			//pPopup->ModifyMenu( 0, MF_BYPOSITION | MF_STRING, ID_WATCH, "Voila, ca marche!!" );
			
			ASSERT(pPopup != NULL); 
			pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
				LOWORD(pos),
				HIWORD(pos),
				AfxGetMainWnd());

			

			break;

		}

		// Get the next item in listview control.
		index++;
	}

	*pResult = 0;
}



void CMyListCtrl::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult) 
{
        HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;

        if( phdn->iButton == 0 )
        {
                // User clicked on header using left mouse button
                if( phdn->iItem == nSortedCol )
                        bSortAscending = !bSortAscending;
                else
                        bSortAscending = TRUE;

                nSortedCol = phdn->iItem;
                SortTextItems( nSortedCol, bSortAscending , 0, -1);

        }
        *pResult = 0;
}




// SortTextItems	- Sort the list based on column text
// Returns		- Returns true for success
// nCol			- column that contains the text to be sorted
// bAscending		- indicate sort order
// low			- row to start scanning from - default row is 0
// high			- row to end scan. -1 indicates last row
BOOL CMyListCtrl::SortTextItems( int nCol, BOOL bAscending, int low /*= 0*/, int high /*= -1*/ )
{
	if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
		return FALSE;

	if( high == -1 ) high = GetItemCount() - 1;

	int lo = low;
	int hi = high;
	CString midItem;

	if( hi <= lo ) return FALSE;

	midItem = GetItemText( (lo+hi)/2, nCol );

	// loop through the list until indices cross
	while( lo <= hi )
	{
		// rowText will hold all column text for one row
		CStringArray rowText;

		// find the first element that is greater than or equal to 
		// the partition element starting from the left Index.
		if( bAscending )
			while( ( lo < high ) && ( GetItemText(lo, nCol) < midItem ) )
				++lo;
		else
			while( ( lo < high ) && ( GetItemText(lo, nCol) > midItem ) )
				++lo;

		// find an element that is smaller than or equal to 
		// the partition element starting from the right Index.
		if( bAscending )
			while( ( hi > low ) && ( GetItemText(hi, nCol) > midItem ) )
				--hi;
		else
			while( ( hi > low ) && ( GetItemText(hi, nCol) < midItem ) )
				--hi;

		// if the indexes have not crossed, swap
		// and if the items are not equal
		if( lo <= hi )
		{
			// swap only if the items are not equal
			if( GetItemText(lo, nCol) != GetItemText(hi, nCol))
			{
				// swap the rows
				LV_ITEM lvitemlo, lvitemhi;
				int nColCount = 
					((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
				rowText.SetSize( nColCount );
				int i;
				for( i=0; i<nColCount; i++)
					rowText[i] = GetItemText(lo, i);
				lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
				lvitemlo.iItem = lo;
				lvitemlo.iSubItem = 0;
				lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED | 
						LVIS_FOCUSED |  LVIS_SELECTED | 
						LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;

				lvitemhi = lvitemlo;
				lvitemhi.iItem = hi;

				GetItem( &lvitemlo );
				GetItem( &lvitemhi );

				for( i=0; i<nColCount; i++)
					SetItemText(lo, i, GetItemText(hi, i));

				lvitemhi.iItem = lo;
				SetItem( &lvitemhi );

				for( i=0; i<nColCount; i++)
					SetItemText(hi, i, rowText[i]);

				lvitemlo.iItem = hi;
				SetItem( &lvitemlo );
			}

			++lo;
			--hi;
		}
	}

	// If the right index has not reached the left side of array
	// must now sort the left partition.
	if( low < hi )
		SortTextItems( nCol, bAscending , low, hi);

	// If the left index has not reached the right side of array
	// must now sort the right partition.
	if( lo < high )
		SortTextItems( nCol, bAscending , lo, high );

	return TRUE;
}
  
