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

#include <z_sclwin.hpp>
#define ZAF_SCROLLED_WINDOW_INFO
#include "gbl_def.cpp"

// ----- ZafScrolledWindow --------------------------------------------------

ZafScrolledWindow::ZafScrolledWindow(int left, int top, int width, int height,
	int scrollWidth, int scrollHeight, int hScrollPos, int vScrollPos) :
	ZafWindow(left, top, width, height)
{
	scrollRegion.coordinateType = coordinateType;
	scrollRegion.left = -hScrollPos;
	scrollRegion.top = -vScrollPos;
	scrollRegion.right = scrollWidth - hScrollPos - 1;
	scrollRegion.bottom = scrollHeight - vScrollPos - 1;
}

ZafScrolledWindow::ZafScrolledWindow(const ZafScrolledWindow &copy) :
	ZafWindow(copy),
	scrollRegion(copy.scrollRegion)
{
}

ZafScrolledWindow::~ZafScrolledWindow(void)
{
}

void ZafScrolledWindow::ConvertCoordinates(ZafCoordinateType newType)
{
	ConvertRegion(zafRegion, newType);
	ConvertRegion(scrollRegion, newType);
}

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

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

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

int ZafScrolledWindow::ScrollHeight(void)
{
	ZafRegionStruct region = scrollRegion;
	ConvertRegion(region, coordinateType);

	return (region.Height());
}

int ZafScrolledWindow::ScrollWidth(void)
{
	ZafRegionStruct region = scrollRegion;
	ConvertRegion(region, coordinateType);

	return (region.Width());
}

int ZafScrolledWindow::HzScrollPos(void)
{
	ZafRegionStruct region = scrollRegion;
	ConvertRegion(region, coordinateType);

	return (-region.left);
}

int ZafScrolledWindow::VtScrollPos(void)
{
	ZafRegionStruct region = scrollRegion;
	ConvertRegion(region, coordinateType);

	return (-region.top);
}

ZafCoordinateType ZafScrolledWindow::SetCoordinateType(ZafCoordinateType newCoordinateType)
{
	// Change scrollRegion coordinateType if the window's coordinateType changes.
	ZafCoordinateType oldCoordType = coordinateType;
	ZafWindowObject::SetCoordinateType(newCoordinateType);
	if (oldCoordType != coordinateType)
		scrollRegion.coordinateType = coordinateType;

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

void ZafScrolledWindow::SetScrollHeight(int setHeight)
{
	// setHeight must be in window's coordinate type.

	// Convert scrollRegion into window's coordinate type so can compare
	// correctly.
	ZafRegionStruct region = scrollRegion;
	ConvertRegion(region, coordinateType);

	// If current position within new height, just recompute scroll bar.
	if (-region.top < setHeight)
	{
		region.bottom = setHeight + region.top - 1;

		// Convert back to scrollRegion coordinate type.
		ConvertRegion(region, scrollRegion.coordinateType);

		// Recompute scroll bar.
		scrollRegion.bottom = region.bottom;
		Event(S_VSCROLL_COMPUTE);
	}
	// Otherwise, the whole scroll area needs to shift and recompute scroll bar.
	else
	{
		region.top = -setHeight;
		region.bottom = -1;

		// Convert back to scrollRegion coordinate type.
		ConvertRegion(region, scrollRegion.coordinateType);

		scrollRegion = region;

		// Shift entire scroll area and recompute scroll bar.
		Event(N_SIZE);
	}
}

void ZafScrolledWindow::SetScrollWidth(int setWidth)
{
	// setWidth must be in window's coordinate type.

	// Convert scrollRegion into window's coordinate type so can compare
	// correctly.
	ZafRegionStruct region = scrollRegion;
	ConvertRegion(region, coordinateType);

	// If current position within new width, just recompute scroll bar.
	if (-region.left < setWidth)
	{
		region.right = setWidth + region.left - 1;

		// Convert back to scrollRegion coordinate type.
		ConvertRegion(region, scrollRegion.coordinateType);

		// Recompute scroll bar.
		scrollRegion.right = region.right;
		Event(S_HSCROLL_COMPUTE);
	}
	// Otherwise, the whole scroll area needs to shift and recompute scroll bar.
	else
	{
		region.left = -setWidth;
		region.right = -1;

		// Convert back to scrollRegion coordinate type.
		ConvertRegion(region, scrollRegion.coordinateType);

		scrollRegion = region;

		// Shift entire scroll area and recompute scroll bar.
		Event(N_SIZE);
	}
}

void ZafScrolledWindow::SetHzScrollPos(int setPos)
{
	// setPos must be in window's coordinate type.

	// Convert scrollRegion into window's coordinate type so can compare
	// correctly.
	ZafRegionStruct region = scrollRegion;
	ConvertRegion(region, coordinateType);

	if (setPos >= 0 && setPos < region.Width())
	{
		// Update region.
		region.left = -setPos;

		// Convert back to scrollRegion coordinate type.
		ConvertRegion(region, scrollRegion.coordinateType);

		// Scroll the window the proper amount.
		ZafEventStruct scrollEvent(S_HSCROLL);
		scrollEvent.scroll.delta = -(region.left - scrollRegion.left);
		Event(scrollEvent);
	}
}

void ZafScrolledWindow::SetVtScrollPos(int setPos)
{
	// setPos must be in window's coordinate type.

	// Convert scrollRegion into window's coordinate type so can compare
	// correctly.
	ZafRegionStruct region = scrollRegion;
	ConvertRegion(region, coordinateType);

	if (setPos >= 0 && setPos < region.Height())
	{
		// Update region.
		region.top = -setPos;

		// Convert back to scrollRegion coordinate type.
		ConvertRegion(region, scrollRegion.coordinateType);

		// Scroll the window the proper amount.
		ZafEventStruct scrollEvent(S_VSCROLL);
		scrollEvent.scroll.delta = -(region.top - scrollRegion.top);
		Event(scrollEvent);
	}
}

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

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

void ZafScrolledWindow::ReadData(ZafObjectPersistence &persist)
{
	ZafFile *file = persist.CurrentFile();

	// Read the data.
	*file >> scrollRegion.left >> scrollRegion.top >> scrollRegion.right >> scrollRegion.bottom;
	scrollRegion.coordinateType = coordinateType;
}

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

void ZafScrolledWindow::WriteData(ZafObjectPersistence &persist)
{
	ZafFile *file = persist.CurrentFile();

	// Write the position and size.
	ZafRegionStruct region = scrollRegion;
	ConvertRegion(region, coordinateType);
	*file << region.left << region.top << region.right << region.bottom;
}
#endif
