//	Zinc Application Framework - Z_TREE.CPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include <z_tree.hpp>
#include <z_string.hpp>
#define ZAF_TREE_INFO
#include "gbl_def.cpp"

// ----- ZafTreeList --------------------------------------------------------

ZafTreeList::ZafTreeList(int left, int top, int width, int height) :
	ZafWindow(left, top, width, height),
	autoSortData(false), drawLines(true)
{
	// Initialize the tree information.
#if !defined(ZAF_TEXT_MODE)
	SetBordered(true);
#endif
	SetDestroyable(false);
	SetMoveable(false);
	SetSizeable(false);

#	if defined(ZAF_MSWINDOWS)
	firstVisible = lastVisible = ZAF_NULLP(ZafTreeItem);
#		if defined(ZAF_WIN32)
	imageList = ZAF_NULLP(ZafTreeImageList);
#		endif
#	elif defined(ZAF_MOTIF)
	itemWidth = itemHeight = 0;
	firstVisible = lastVisible = cancelObject = viewCurrent = ZAF_NULLP(ZafTreeItem);
#	elif defined(ZAF_INDEPENDENT)
	firstVisible = lastVisible = viewCurrent = ZAF_NULLP(ZafTreeItem);
#	endif
}

ZafTreeList::ZafTreeList(const ZafTreeList &copy) :
	ZafWindow(copy),
	autoSortData(copy.autoSortData), drawLines(copy.drawLines)
{
	// Copy the compareFunction.
	SetCompareFunction(copy.CompareFunction());
	
#	if defined(ZAF_MSWINDOWS)
	firstVisible = lastVisible = ZAF_NULLP(ZafTreeItem);
#		if defined(ZAF_WIN32)
	imageList = ZAF_NULLP(ZafTreeImageList);
#		endif
#	elif defined(ZAF_MOTIF)
	itemWidth = itemHeight = 0;
	firstVisible = lastVisible = cancelObject = viewCurrent = ZAF_NULLP(ZafTreeItem);
#	elif defined(ZAF_INDEPENDENT)
	firstVisible = lastVisible = viewCurrent = ZAF_NULLP(ZafTreeItem);
#	endif
}

ZafTreeList::~ZafTreeList(void)
{
}

ZafTreeItem *ZafTreeList::DepthCurrent(void)
{
	ZafTreeItem *object = DynamicPtrCast(current, ZafTreeItem);
	return (object ? object->DepthCurrent() : ZAF_NULLP(ZafTreeItem));
}

ZafTreeItem *ZafTreeList::DepthFirst(void)
{
	return (DynamicPtrCast(first, ZafTreeItem));
}

ZafTreeItem *ZafTreeList::DepthLast(void)
{
	ZafTreeItem *object = DynamicPtrCast(last, ZafTreeItem);
	return (object ? object->DepthLast() : ZAF_NULLP(ZafTreeItem));
}

ZafWindowObject *ZafTreeList::Duplicate(void)
{
	return (new ZafTreeList(*this));
}

ZafTreeItem *ZafTreeList::FirstVisible(void) const
{
	return (firstVisible);
}

bool ZafTreeList::IsA(ZafClassID compareID) const
{
	return ((compareID == classID || compareID == ID_ZAF_LIST) ? true : ZafWindow::IsA(compareID));
}

bool ZafTreeList::IsA(ZafClassName compareName) const
{
	return (!strcmp(compareName, className) ? true : ZafWindow::IsA(compareName));
}

ZafTreeItem *ZafTreeList::LastVisible(void) const
{
	return (lastVisible);
}

ZafLogicalEvent ZafTreeList::LogicalEvent(const ZafEventStruct &event)
{
	ZafLogicalEvent ccode = MapEvent(defaultEventMap, event);
	return ((ccode == L_NONE) ? ZafWindow::LogicalEvent(event) : ccode);
}

const ZafPaletteStruct *ZafTreeList::MapClassPalette(ZafPaletteType type, ZafPaletteState state)
{
	const ZafPaletteStruct *palette = MapPalette(defaultPaletteMap, type, state);
	return (palette ? palette : ZafWindow::MapClassPalette(type, state));
}

bool ZafTreeList::SetAutoSortData(bool tAutoSortData)
{
	// Make sure the attribute has changed.
	if (autoSortData != tAutoSortData)
	{
		autoSortData = tAutoSortData;

		// Reset the sort function.
		if (autoSortData)
		{
			if (!compareFunction)
				SetCompareFunction((ZafCompareFunction)CompareAscending);
			Sort();
		}
		else if (compareFunction == (ZafCompareFunction)CompareAscending)
			compareFunction = ZAF_NULLF(ZafCompareFunction);
	}

	// Return the current attribute.
	return autoSortData;
}

ZafLogicalColor ZafTreeList::SetBackgroundColor(ZafLogicalColor color, ZafLogicalColor mono)
{
	// Make sure there is a userPalette.
	if (!userPaletteData)
		SetUserPaletteData(new ZafPaletteData());

	// Add the background color entry.
	ZafPaletteStruct backgroundPalette = userPaletteData->GetPalette(ZAF_PM_BACKGROUND, ZAF_PM_ANY_STATE);
	backgroundPalette.colorBackground = color;
	backgroundPalette.monoBackground = mono;
	userPaletteData->AddPalette(ZAF_PM_BACKGROUND, ZAF_PM_ANY_STATE, backgroundPalette);

	// Add the selected text color entry.
	backgroundPalette = userPaletteData->GetPalette(ZAF_PM_TEXT, ZAF_PM_SELECTED | ZAF_PM_ENABLED);
	backgroundPalette.colorForeground = color;
	backgroundPalette.monoForeground = mono;
	userPaletteData->AddPalette(ZAF_PM_TEXT, ZAF_PM_SELECTED | ZAF_PM_ENABLED, backgroundPalette);

	// Return the current color.
	return (color);
}

ZafCompareFunction ZafTreeList::SetCompareFunction(ZafCompareFunction tCompareFunction)
{
	for (ZafTreeItem *item = (ZafTreeItem *)first; item; item = (ZafTreeItem *)item->Next())
		item->SetCompareFunction(tCompareFunction);
	return (ZafList::SetCompareFunction(tCompareFunction));
}

bool ZafTreeList::SetCopyDraggable(bool setCopyDraggable)
{
	// Defer to the root class.
	return (ZafWindowObject::SetCopyDraggable(setCopyDraggable));
}

bool ZafTreeList::SetDestroyable(bool )
{
	// destroyable is false for this class.
	destroyable = false;
	return (destroyable);
}

bool ZafTreeList::SetDrawLines(bool setDrawLines)
{
	// Change the attribute.
	if (drawLines != setDrawLines && !screenID)
		drawLines = setDrawLines;

	// Return the current attribute.
	return (drawLines);
}

ZafTreeItem *ZafTreeList::SetFirstVisible(ZafTreeItem *tFirstVisible)
{
	firstVisible = tFirstVisible;
	return (firstVisible);
}

bool ZafTreeList::SetFocus(bool setFocus)
{
	// Defer to the base class.
	return (ZafWindowObject::SetFocus(setFocus));
}

bool ZafTreeList::SetLinkDraggable(bool setLinkDraggable)
{
	// Defer to the root class.
	return (ZafWindowObject::SetLinkDraggable(setLinkDraggable));
}

bool ZafTreeList::SetLocked(bool )
{
	// locked is false for this class.
	locked = false;
	return (locked);
}

bool ZafTreeList::SetMaximized(bool )
{
	// maximized is false for this class.
	maximized = false;
	return (maximized);
}

bool ZafTreeList::SetMinimized(bool )
{
	// minimized is false for this class.
	minimized = false;
	return (minimized);
}

bool ZafTreeList::SetModal(bool )
{
	// modal is false for this class.
	modal = false;
	return (modal);
}

bool ZafTreeList::SetMoveable(bool )
{
	// moveable is false for this class.
	moveable = false;
	return (moveable);
}

bool ZafTreeList::SetMoveDraggable(bool setMoveDraggable)
{
	// Defer to the root class.
	return (ZafWindowObject::SetMoveDraggable(setMoveDraggable));
}

bool ZafTreeList::SetNormalHotKeys(bool )
{
	// normalHotKeys is false for this class.
	normalHotKeys = false;
	return (normalHotKeys);
}

ZafWindow *ZafTreeList::SetOwner(ZafWindow *)
{
	// owner is null for this class.
	owner = ZAF_NULLP(ZafWindow);
	return (owner);
}

ZafSelectionType ZafTreeList::SetSelectionType(ZafSelectionType setSelectionType)
{
	// Set the object and update all the children.
	ZafWindow::SetSelectionType(setSelectionType);
	for (ZafTreeItem *item = First(); item; item = item->Next())
		item->SetSelectionType(selectionType);

	// Return the current attribute.
	return (selectionType);
}

bool ZafTreeList::SetSizeable(bool )
{
	// sizeable is false for this class.
	sizeable = false;
	return (sizeable);
}

bool ZafTreeList::SetTemporary(bool )
{
	// temporary is false for this class.
	temporary = false;
	return (temporary);
}

ZafLogicalColor ZafTreeList::SetTextColor(ZafLogicalColor color, ZafLogicalColor mono)
{
	// Make sure there is a userPalette.
	if (!userPaletteData)
		SetUserPaletteData(new ZafPaletteData());

	// Add the text color entry.
	ZafPaletteStruct textPalette = userPaletteData->GetPalette(ZAF_PM_TEXT, ZAF_PM_ENABLED);
	textPalette.colorForeground = color;
	textPalette.monoForeground = mono;
	userPaletteData->AddPalette(ZAF_PM_TEXT, ZAF_PM_ENABLED, textPalette);

	// Add the selected backgound color entry.
//	textPalette = userPaletteData->GetPalette(ZAF_PM_BACKGROUND, ZAF_PM_SELECTED);
	textPalette = userPaletteData->GetPalette(ZAF_PM_TEXT, ZAF_PM_SELECTED);
	textPalette.colorBackground = color;
	textPalette.monoBackground = mono;
	userPaletteData->AddPalette(ZAF_PM_TEXT, ZAF_PM_SELECTED, textPalette);
//	userPaletteData->AddPalette(ZAF_PM_BACKGROUND, ZAF_PM_SELECTED, textPalette);

	// Return the current color.
	return (color);
}

int ZafTreeList::ViewCount(void)
{
	// Count the list items.
	int tCount = 0;
	for (ZafTreeItem *item = ViewFirst(); item; item = item->ViewNext())
		tCount++;
	return (tCount);
}

ZafTreeItem *ZafTreeList::ViewFirst(void)
{
	return (DynamicPtrCast(first, ZafTreeItem));
}

ZafTreeItem *ZafTreeList::ViewLast(void)
{
	ZafTreeItem *object = DynamicPtrCast(last, ZafTreeItem);
	return (object ? object->ViewLast() : ZAF_NULLP(ZafTreeItem));
}

// ----- Persistent functions -----------------------------------------------
#if defined(USE_ZAF_PERSISTENCE)
ZafTreeList::ZafTreeList(const ZafIChar *name, ZafObjectPersistence &persist) :
	ZafWindow(name, persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY))
{
	// Read the data.
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafTreeList::ReadData(persist);

	// Set all children as non-system objects.  ZafWindow persistent
	// constructor will not call ZafVtList::Add() since it is in the base
	// class phase of construction when the children are added.
	for (ZafWindowObject *object = First(); object; object = object->Next())
	{
		object->SetSystemObject(false);
		object->SetParentPalette(true);
	}

	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());

#	if defined(ZAF_MSWINDOWS)
	firstVisible = lastVisible = ZAF_NULLP(ZafTreeItem);
#		if defined(ZAF_WIN32)
	imageList = ZAF_NULLP(ZafTreeImageList);
#		endif
#	elif defined(ZAF_MOTIF)
	itemWidth = itemHeight = 0;
	firstVisible = lastVisible = cancelObject = viewCurrent = ZAF_NULLP(ZafTreeItem);
#	elif defined(ZAF_INDEPENDENT)
	firstVisible = lastVisible = viewCurrent = ZAF_NULLP(ZafTreeItem);
#	endif
}

ZafWindowObject *ZafTreeList::AddDepthItem(const ZafIChar *pathName, ZafWindowObject *object)
{
	// Check for tree-list addition.
	if (!pathName || !pathName[0])
		return (Add(object));

	// Find the appropriate insertion spot.
	ZafWindowObject *findObject = GetObject(pathName);
	if (!findObject)
		return (ZAF_NULLP(ZafWindowObject));

	// Check at the tree level.
	if (findObject == this)
		return (Add(object));

	// Check at a tree item level.
	ZafTreeItem *treeItem = DynamicPtrCast(findObject, ZafTreeItem);
	if (treeItem)
		return (treeItem->Add(object));

	// Fail.
	return (ZAF_NULLP(ZafWindowObject));
}

ZafElement *ZafTreeList::Read(const ZafIChar *name, ZafObjectPersistence &persist)
{
	return (new ZafTreeList(name, persist));
}

void ZafTreeList::ReadData(ZafObjectPersistence &persist)
{
	// Read the data.
	ZafUInt16 flag1;
	ZafFile *file = persist.CurrentFile();
	*file >> flag1;
	autoSortData = (flag1 & 0x0001) ? true : false;
	drawLines = (flag1 & 0x0002) ? true : false;
	if (autoSortData)
		SetCompareFunction((ZafCompareFunction)CompareAscending);
}

void ZafTreeList::Write(ZafObjectPersistence &persist)
{
	// Write the object.
	ZafWindow::Write(persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY));
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafTreeList::WriteData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

void ZafTreeList::WriteData(ZafObjectPersistence &persist)
{
	// Write the data.
	ZafUInt16 flag1 = 0;
	ZafFile *file = persist.CurrentFile();
	flag1 |= (ZafUInt16)(autoSortData ? 0x0001 : 0);
	flag1 |= (ZafUInt16)(drawLines ? 0x0002 : 0);
	*file << flag1;
}
#endif
