/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	FolderTreeView.cpp
 *
 *****************************************************************************/

// SOL++2000

#include <sol\FolderTreeView.h>


FolderTreeView::FolderTreeView(View* parent, const char* name, Args& args)
	:TreeView(parent, name,
		args.set(XmNexStyle, (ulong)WS_EX_CLIENTEDGE)
	        .set(XmNstyle, (ulong)TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT) )

{
	imageList = NULL;
	HINSTANCE hInst = getInstanceHandle();

	imageList = new ImageList(16, 16, ILC_COLOR24, 2,1);

	char dir[_MAX_PATH];
	::GetWindowsDirectory(dir, sizeof(dir));
	SHFILEINFO shfi;
	::SHGetFileInfo(dir, FILE_ATTRIBUTE_DIRECTORY,
			&shfi, sizeof(shfi), SHGFI_ICON|SHGFI_SMALLICON);

	imageList -> setBkColor(::GetSysColor(COLOR_WINDOW));
	iconId   = imageList -> addIcon(shfi.hIcon);

	::SHGetFileInfo(dir, FILE_ATTRIBUTE_DIRECTORY,
		&shfi, sizeof(shfi), 
		SHGFI_ICON|SHGFI_OPENICON|SHGFI_SMALLICON);
	selIconId = imageList -> addIcon(shfi.hIcon); 

	setImageList(imageList, 0);
}


FolderTreeView::~FolderTreeView()
{
	delete imageList; 
}

Boolean FolderTreeView::create(View* parent, const char* name, Args& args)
{
	Boolean rc = TreeView::create(parent, name,
		args.set(XmNexStyle, (ulong)WS_EX_CLIENTEDGE)
	        .set(XmNstyle, (ulong)TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT) );

	imageList = NULL;
	HINSTANCE hInst = getInstanceHandle();

	imageList = new ImageList(16, 16, ILC_COLOR24, 2,1);

	char dir[_MAX_PATH];
	::GetWindowsDirectory(dir, sizeof(dir));
	SHFILEINFO shfi;
	::SHGetFileInfo(dir, FILE_ATTRIBUTE_DIRECTORY,
			&shfi, sizeof(shfi), SHGFI_ICON|SHGFI_SMALLICON);

	imageList -> setBkColor(::GetSysColor(COLOR_WINDOW));
	iconId   = imageList -> addIcon(shfi.hIcon);

	::SHGetFileInfo(dir, FILE_ATTRIBUTE_DIRECTORY,
		&shfi, sizeof(shfi), 
		SHGFI_ICON|SHGFI_OPENICON|SHGFI_SMALLICON);
	selIconId = imageList -> addIcon(shfi.hIcon); 

	setImageList(imageList, 0);

	return rc;
}


void FolderTreeView::buildDirTree()
{
	char dir[_MAX_PATH];
	::GetWindowsDirectory(dir, sizeof(dir));

	char path[10];
	DWORD d = ::GetLogicalDrives();

	HTREEITEM item = NULL;
	for(int i = 0; i<26; i++) {
		if(d & 1) {
			wsprintf(path, "%c:", 'A'+i);
			item = addItem(NULL, TVI_LAST, path);
			findDirectories(item, dir, 0, 2);
			sortChildren(item, TRUE);
			if(path[0] == dir[0]) {
				expand(item, TVE_EXPAND);
			}
		}
		d = d >> 1;
	}
}


HTREEITEM FolderTreeView::hasEntry(HTREEITEM child, const char* name)
{
	HTREEITEM found = NULL;
	HTREEITEM item = child;
	while(item) {
		TV_ITEM hitem;

		char text[_MAX_PATH];
		hitem.mask       = TVIF_TEXT|TVIF_HANDLE;
		hitem.hItem      = item;
		hitem.pszText    = text;
		hitem.cchTextMax = _MAX_PATH;
		getItem(&hitem);
	
		if(strcmp(text, name) == 0) {
			found = item;
			break;
		}
		item = getNextSibling(item);
	}
	return found;
}


void FolderTreeView::findDirectories(HTREEITEM parent, const char* dir,
				  int level, int max)
{
	if(level < max) {
		WIN32_FIND_DATA data;
		HTREEITEM item = (HTREEITEM)TVI_FIRST;

		char* buffer = new char[_MAX_PATH];
		wsprintf(buffer, "%s\\*", dir);
		HANDLE fFile= ::FindFirstFile(buffer, &data);

		HTREEITEM child = getChild(parent);

		if(fFile != INVALID_HANDLE_VALUE) {
			do {
				if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
					if (strcmp(".", data.cFileName) != 0 && 
						strcmp("..", data.cFileName) != 0) {

						item = hasEntry(child, data.cFileName);

						// 同じ名前のエントリがなければ、追加する。
						if(item == NULL) {
							item = addItem(parent, item, 
										data.cFileName,
										iconId, selIconId);
						}
						char* subDir = new char[_MAX_PATH];
						wsprintf(subDir, "%s\\%s", dir, data.cFileName);
				
						findDirectories(item, (const char*)subDir,
								level+1, max);
						delete [] subDir;
					}
				}
			} while(FindNextFile(fFile, &data)); 
			::FindClose(fFile);
		}
		delete [] buffer;
	}
}


// 階層関係（ディレクトリの場合はフルパス名）を取得する
void FolderTreeView::getHierachy(HTREEITEM selItem, char* buff, char* delim)
{
	TV_ITEM hitem;

	HTREEITEM parent = getParent(selItem);
	if(parent) {
		// 親ノードの処理
		getHierachy(parent, buff, delim);
		char* text       = new char[_MAX_PATH];
		hitem.mask       = TVIF_TEXT|TVIF_HANDLE;
		hitem.hItem      = selItem;
		hitem.pszText    = text;
		hitem.cchTextMax = _MAX_PATH;
		getItem(&hitem);
		strcat(buff, delim);
		strcat(buff, text);
		delete [] text;
	}
	else {
		char* text       = new char[_MAX_PATH];
		hitem.mask       = TVIF_TEXT|TVIF_HANDLE;
		hitem.hItem      = selItem;
		hitem.pszText    = text;
		hitem.cchTextMax = _MAX_PATH;
		getItem(&hitem);
		strcat(buff, text);
		delete [] text;
	}
}
