/************************************************
   THIS CODE AND INFORMATION IS PROVIDED 'AS IS' 
   WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO
   THE IMPLIED WARRANTIES OF MERCHANTABILITY 
   AND/OR FITNESS FOR A PARTICULAR PURPOSE.
   Author: Barretto VN  7/2002
*************************************************/


/********************************************************************************/
/* Include files								*/
/********************************************************************************/

#include "CCsplitter.h"
#include "resource.h"

#include <stdio.h>
#include <commctrl.h>
#include <shlobj.h>

#include "ShellFunc.h"
#include "TreeView.h"
#include "ListView.h"

#include "lptvid.h"
/********************************************************************************/
/* Constant definitions								*/
/********************************************************************************/

/********************************************************************************/
/* Function prototypes								*/
/********************************************************************************/

LRESULT CALLBACK MainWindowProc (
    HWND	hWnd,			// Window handle
    UINT	uMsg,			// Message code
    WPARAM	wParam,			// Message parameter
    LPARAM	lParam			// Message parameter
);
HWND explorer(HINSTANCE appInstance, HWND hParent);
void	CreateSplitter (HWND hParent);
BOOL WINAPI CreateStatusBar (HWND hOwnerWnd);
BOOL WINAPI CreateToolBar (HWND hOwnerWnd);
void    SetSplit(HWND hWnd);
void    CreateImageLists();

void 	BeginDrag(HWND hWndListView, NMLISTVIEW *lvItem);
void 	DropItem(LVITEM hSourceItem, HTREEITEM hTargetItem);
BOOL    MoveImage(POINT point);

/********************************************************************************/
/* Private data definitions							*/
/********************************************************************************/

static	HINSTANCE   appInstance;	// Application instance handle

static const char *sTitle = "Win32 System Browser";
static const char *sDeveloper = "Developer Barretto VN\nE-Mail : barretto_vn@mail.com";

#define TOOLBAR_HT   26
#define STATUSBAR_HT 15

static	HWND	    hSplitter;		// Splitter control window handle

HWND    hWndMain;
HWND    hWndTreeView;
HWND    hWndListView;
HWND    ghStatusBar;
HWND    ghToolBar;

HIMAGELIST	himlSmall = NULL;
HIMAGELIST	himlLarge = NULL;
BOOL	    g_fDragging = FALSE;
POINT       g_ptHotSpot; 
RECT        g_rcImage; 

/********************************************************************************/
/* Public procedure definitions							*/
/********************************************************************************/

HWND explorer(HINSTANCE hInstance, HWND hParent)
{
    WNDCLASSEX	wc;			// Window class data
    MSG		msg;			// Message data

	INITCOMMONCONTROLSEX iccex;

	//required to use the common controls
	iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
	iccex.dwICC = ICC_LISTVIEW_CLASSES;
	InitCommonControlsEx(&iccex);

    appInstance = hInstance;

    if (!InitCCsplitter ()) 
	{
		MessageBox (NULL, "InitCCsplitter failed in WinMain", NULL, MB_ICONSTOP|MB_OK);
		return 1;
    }

    ZeroMemory (&wc, sizeof (wc));
    wc.cbSize	     = sizeof (wc);
    wc.hInstance     = hInstance;
    wc.hCursor	     = LoadCursor (hInstance, MAKEINTRESOURCE(IDC_SPLIT_CURSOR)); //(NULL, IDC_ARROW);
    wc.hIcon	     = LoadIcon (appInstance, MAKEINTRESOURCE(IDI_MAINICON)); //IDI_APPLICATION);
    wc.hIconSm	     = LoadIcon (appInstance, MAKEINTRESOURCE(IDI_MAINICON)); //IDI_APPLICATION);
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); //NULL;
    wc.lpfnWndProc   = MainWindowProc;
    wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MAINMENU);
    wc.lpszClassName = "Win32ExplorerMainWindow";
    RegisterClassEx (&wc);

    hWndMain = CreateWindowEx (
	                       0,					// Extended window style
	                       wc.lpszClassName,			// Window class name
	                       "Win 32 System Browser",			// Window name
	                       WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,	// Window style
	                       CW_USEDEFAULT,				// Horizontal position
	                       CW_USEDEFAULT,				// Vertical position
	                       CW_USEDEFAULT, 				// Width
	                       CW_USEDEFAULT, 				// Height
	                       hParent,					// Parent window handle
	                       NULL,					// Menu handle
	                       hInstance,				// Application instance
 	                       0);					// Parameter

    if (hWndMain == NULL) 
	{
		MessageBox (0, "CreateWindowEx failed in WinMain", NULL, MB_ICONSTOP|MB_OK);
		return 1;
    }

    ShowWindow (hWndMain, SW_SHOW);

    return hWndMain;
}

/********************************************************************************/
/* Private procedure definitions						*/
/********************************************************************************/

static	LRESULT CALLBACK MainWindowProc (
	                                     HWND	hWnd,			// Window handle
	                                     UINT	uMsg,			// Message code
	                                     WPARAM	wParam,			// Message parameter
	                                     LPARAM	lParam)			// Message parameter
{
//HDC hdc;
HMENU	hMenu;			// Menu handle
LVITEM lvItem;
LVITEM hSourceItem;
HTREEITEM hTargetItem;
TVITEM tvItem;
TVHITTESTINFO tvHit;       // Hit test information
HTREEITEM hTarget, hPrevItem = NULL;
RECT rect;

hSourceItem.iItem = -1;

    hMenu = GetMenu (hWnd);

    switch (uMsg) {

	case WM_COMMAND:
		switch(LOWORD(wParam)) 
		{

			case IDM_FILE_EXIT:
			    SendMessage (hWnd, WM_CLOSE, 0, 0);
			    break;
		    case IDM_HELP_ABOUT:
				ShellAbout(NULL, 
					       sTitle , 
						   sDeveloper , 
						   LoadIcon (appInstance, MAKEINTRESOURCE(IDI_MAINICON)));
			    break;
			case IDM_VIEW_LARGEICONS:
				onViewStyle(LOWORD(wParam) , hWndMain);
				break;
			case IDM_VIEW_SMALLICONS:
				onViewStyle(LOWORD(wParam), hWndMain);
				break;
			case IDM_VIEW_LIST:
				onViewStyle(LOWORD(wParam), hWndMain);
				break;
			case IDM_VIEW_DETAIL:
				onViewStyle(LOWORD(wParam), hWndMain);
				break;

		}

		return TRUE;
	
	case WM_CREATE:

		CreateSplitter (hWnd);
		hWndTreeView = CreateTreeView (appInstance, hWnd, hSplitter);
		hWndListView = CreateListView (appInstance, hWnd, hSplitter);
		CreateStatusBar(hWnd);
        CreateToolBar (hWnd);
		SetSplit(hWnd);
		CreateImageLists();
		InitTreeView();

		break;

	case WM_DESTROY:
		PostQuitMessage (0);
		return TRUE;

	case WM_NOTIFY:
		switch (((NMHDR *)lParam)->idFrom)
		{
			case ID_TREEVIEW:
			{
				tvItem = ((NM_TREEVIEW*)lParam)->itemNew;
				if(((NMHDR *)lParam)->code == TVN_ITEMEXPANDING)
				{
					PopulateTree(tvItem); 
				}
				if(((NMHDR *)lParam)->code == TVN_SELCHANGING)
				{
					PopulateList(tvItem); 
				}
				break;
			}

			case ID_LISTVIEW:
			{IShellFolder *psfProgFiles = NULL;
			LPTVITEMDATA* lptvid = NULL;
			LPITEMIDLIST pidlItems = NULL;
				char fn[256];
			    ZeroMemory(&lvItem, sizeof(lvItem));
				
				
				lvItem.pszText = fn;
				lvItem.cchTextMax = 256;
				
			    GetSelectedItem((LPNMHDR)lParam , &lvItem);
				/*
				lptvid = (LPTVITEMDATA*)lvItem.lParam;
				if (lptvid->bRoot)
					psfProgFiles = lptvid->lpsfParent;
				else
				{
					lptvid->lpsfParent->lpVtbl->BindToObject(lptvid->lpsfParent , lptvid->lpi, NULL, &IID_IShellFolder, (LPVOID *) &psfProgFiles);
				}*/
				if((((NMHDR *)lParam)->code == NM_DBLCLK) ||
					(((NMHDR *)lParam)->code == NM_RCLICK))
				{

				  ShowStdMenu(lvItem , ((NMHDR *)lParam)->code == NM_DBLCLK ? FALSE : TRUE , appInstance);
				  //psfProgFiles->lpVtbl->GetDisplayNameOf(psfProgFiles, pidlItems, /*SHGDN_INFOLDER | SHGDN_FOREDITING */SHGDN_FORPARSING , fn);

				}
				if(((NMHDR *)lParam)->code == LVN_GETDISPINFO) 
				{
					LV_DISPINFO    *lpdi = (LV_DISPINFO *)(LPNMHDR)lParam;
					setDisplayInfo(lpdi);
					lpdi->item.mask |= LVIF_DI_SETITEM;	// dont ask us again
				}
				if(((NMHDR *)lParam)->code == LVN_BEGINDRAG) 
				{
					BeginDrag(hWndListView, (NMLISTVIEW*)lParam);
					hSourceItem = lvItem;
				}

				break;
			}
		}
		break;

	case WM_MOUSEMOVE:
		// if dragging, move the image
		if (g_fDragging)
		{
			tvHit.pt.x = LOWORD(lParam);
			tvHit.pt.y = HIWORD(lParam);

			ImageList_DragEnter( hWnd, tvHit.pt.x , tvHit.pt.y); 

			// drag the item to the current mouse position
			ImageList_DragMove(tvHit.pt.x, tvHit.pt.y); 

			// if the cursor is on an item, hilite it as
			// the drop target

			if ((hTarget = TreeView_HitTest(hWndTreeView, &tvHit)) != NULL)
			{
				TreeView_Select(hWndTreeView, hTarget, TVGN_DROPHILITE);

				TreeView_GetItemRect(hWndTreeView, hTarget, &rect , FALSE);
				InvalidateRect(hWndTreeView, &rect, TRUE);

				if(tvHit.flags & TVHT_ONITEMRIGHT | TVHT_ONITEMBUTTON)
				{
					if(hTarget != hPrevItem)
					{
						TreeView_Expand(hWndTreeView, hTarget, TVE_TOGGLE);
						hPrevItem = hTarget;
					}
				}
			}
		}
		break;

	case WM_LBUTTONUP:
		// If dragging, stop it.
		if (g_fDragging)
		{
			// Process the item drop.
			tvHit.pt.x = LOWORD(lParam);
			tvHit.pt.y = HIWORD(lParam);
			if((hTargetItem = TreeView_HitTest(hWndTreeView, &tvHit)) != NULL)
				DropItem(hSourceItem, hTargetItem);
				
			// Inform the image list that dragging has stopped.
			ImageList_EndDrag();
			ImageList_DragLeave(hWnd);

			// Release the mouse.
			ReleaseCapture();

			// Show the cursor.
			ShowCursor(TRUE);

			// Reset the global Boolean flag to a nondragging state.
			g_fDragging = FALSE;

			GetClientRect(hWndTreeView, &rect);
			InvalidateRect(hWndTreeView, &rect, TRUE);
			
		}
		break;

	case WM_SIZE:
		MoveWindow (hSplitter, 0, TOOLBAR_HT, LOWORD (lParam), HIWORD (lParam) - 46, TRUE);
		MoveWindow (ghToolBar, 0, 0, LOWORD (lParam), TOOLBAR_HT, TRUE);
        MoveWindow (ghStatusBar, 0 , HIWORD (lParam) - STATUSBAR_HT , LOWORD (lParam) , HIWORD (lParam) - STATUSBAR_HT, TRUE);
		break;
    }

    return DefWindowProc (hWnd, uMsg, wParam, lParam);
}


static	void	CreateSplitter(HWND	hParent)		// Parent window handle
{
    // Create the splitter control

    hSplitter = CreateWindowEx (
                             	0,				// Extended window style
	                            WC_CCSPLITTER,			// Window class name
	                            NULL,				// Window name
	                            WS_CHILD|WS_VISIBLE,		// Window style
	                            0, 0, 0, 0,			// Position & size
	                            hParent,			// Parent window handle
	                            (HMENU)ID_SPLITTER,		// Application defined ID
	                            appInstance,			// Application instance
	                            0);				// Parameter

    if (hSplitter == NULL) 
	{
		MessageBox (0, "CreateWindowEx failed in CreateChildWindows", NULL, MB_ICONSTOP|MB_OK);
		exit (1);
    }

}

BOOL WINAPI CreateToolBar (HWND hOwnerWnd) 
{     
#define NUMBER_OF_TB_BUTTONS 6
#define NUMBER_OF_SEPARATORS 1
#define BUTTON_1   0
#define BUTTON_2   1
#define BUTTON_3   2
#define BUTTON_4   3
#define BUTTON_5   4
#define BUTTON_6   5
#define BUTTON_7   6


	// Initialize each of the buttons with the appropiate values     
	TBBUTTON tbButton[NUMBER_OF_TB_BUTTONS] = { 0 };      

	tbButton[BUTTON_1].iBitmap   = VIEW_LARGEICONS;     
	tbButton[BUTTON_1].idCommand = IDM_VIEW_LARGEICONS;     
	tbButton[BUTTON_1].fsState   = TBSTATE_ENABLED;     
	tbButton[BUTTON_1].fsStyle   = TBSTYLE_BUTTON;      
	
	tbButton[BUTTON_2].iBitmap   = VIEW_SMALLICONS;     
	tbButton[BUTTON_2].idCommand = IDM_VIEW_SMALLICONS;     
	tbButton[BUTTON_2].fsState   = TBSTATE_ENABLED;     
	tbButton[BUTTON_2].fsStyle   = TBSTYLE_BUTTON;      

	tbButton[BUTTON_3].iBitmap   = VIEW_LIST;     
	tbButton[BUTTON_3].idCommand = IDM_VIEW_LIST;     
	tbButton[BUTTON_3].fsState   = TBSTATE_ENABLED;     
	tbButton[BUTTON_3].fsStyle   = TBSTYLE_BUTTON;      

	tbButton[BUTTON_4].iBitmap   = VIEW_DETAILS;     
	tbButton[BUTTON_4].idCommand = IDM_VIEW_DETAIL;     
	tbButton[BUTTON_4].fsState   = TBSTATE_ENABLED;     
	tbButton[BUTTON_4].fsStyle   = TBSTYLE_BUTTON;      

	tbButton[BUTTON_5].fsStyle   = TBSTYLE_SEP;     
	
	tbButton[BUTTON_6].iBitmap   = STD_HELP;     
	tbButton[BUTTON_6].idCommand = IDM_HELP_ABOUT;     
	tbButton[BUTTON_6].fsState   = TBSTATE_ENABLED;     
	tbButton[BUTTON_6].fsStyle   = TBSTYLE_BUTTON;      

	// Create the toolbar with the most commonly used functions     

	ghToolBar = CreateToolbarEx (
		hOwnerWnd, 
		WS_CHILD | WS_BORDER | WS_VISIBLE | WS_CHILD | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT , 
		IDB_TOOLBAR, 
		11, 
		(HINSTANCE)HINST_COMMCTRL, 
		IDB_VIEW_SMALL_COLOR, 
		(LPCTBBUTTON)&tbButton, 
		NUMBER_OF_TB_BUTTONS, 
		0, 0, 0, 0, 
		sizeof (TBBUTTON));

	if (NULL == ghToolBar)     
	{         
	    MessageBox (0, "failed to create ToolBar", NULL, MB_ICONSTOP|MB_OK);
		return FALSE;     
	}     

	return TRUE; 
}  

BOOL WINAPI CreateStatusBar (HWND hOwnerWnd) 
{     
	ghStatusBar = CreateStatusWindow (
		WS_BORDER | WS_CHILD | WS_VISIBLE,
		TEXT("Ready"),
		hOwnerWnd, 
		IDC_STATUSBAR);     

	if (ghStatusBar == NULL)     
	{         
		return FALSE;    
	}     
	
	return TRUE; 
}  

void    SetSplit(HWND hWnd)
{
RECT	rc;			// Window rectangle
CCSPLIT	spx;		// X-split data

    spx.cbSize = sizeof (spx);
    GetClientRect (hWnd, &rc);
    spx.flags  = CCSP_POS;
    spx.pos    = rc.right/3;
    CCsplitter_SetSplit (hSplitter, &spx, NULL);
}

void CreateImageLists()
{
SHFILEINFO  sfi;

	himlSmall = (HIMAGELIST)SHGetFileInfo( TEXT("C:\\"), 
                                       0,
                                       &sfi, 
                                       sizeof(SHFILEINFO), 
                                       SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

	himlLarge = (HIMAGELIST)SHGetFileInfo( TEXT("C:\\"), 
                                       0,
                                       &sfi, 
                                       sizeof(SHFILEINFO), 
                                       SHGFI_SYSICONINDEX | SHGFI_LARGEICON);

	if (himlSmall && himlLarge)
   {
		SendMessage(hWndTreeView, TVM_SETIMAGELIST, (WPARAM)LVSIL_NORMAL, (LPARAM)himlSmall);
		SendMessage(hWndTreeView, TVM_SETIMAGELIST, (WPARAM)LVSIL_STATE, (LPARAM)himlSmall);

		SendMessage(hWndListView, LVM_SETIMAGELIST, (WPARAM)LVSIL_SMALL, (LPARAM)himlSmall);
		SendMessage(hWndListView, LVM_SETIMAGELIST, (WPARAM)LVSIL_NORMAL, (LPARAM)himlLarge);
   }
}

void 	BeginDrag(HWND hwndLV, NMLISTVIEW *lvItem)
{
	POINT point;
	HIMAGELIST hIml;
	RECT rcl;
	point.x = point.y = 0;
	GetCursorPos(&point);
	hIml = ListView_CreateDragImage(hwndLV, lvItem->iItem, &point);
	ListView_GetItemRect(hwndLV, lvItem->iItem, &rcl, LVIR_SELECTBOUNDS);

	ImageList_BeginDrag(hIml, 0, 10, -35);
//	ImageList_BeginDrag(hIml, 0, point.x - rcl.left , point.y - rcl.top);

	ShowCursor(FALSE);
	// Capture the mouse.

	SetCapture(GetParent(hwndLV));

	// Set a global flag that tells whether dragging is occurring.
	g_fDragging = TRUE;

}

void 	DropItem(LVITEM hSourceItem, HTREEITEM hTargetItem)
{

}

BOOL MoveImage(POINT point)
{
    return ImageList_DragMove(point.x,  point.y);
}


/********************************************************************************/
/* End of file									*/
/********************************************************************************/
