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

#include <z_gmgr.hpp>

// ----- ZafRelativeConstraint ----------------------------------------------

ZafRelativeConstraint::ZafRelativeConstraint(ZafWindowObject *zObject,
	ZafRelativeConstraintType zType) :
	ZafConstraint(zObject),
	ratio(0), type(zType), stretch(false), oppositeSide(false), center(false)
{
}

ZafRelativeConstraint::ZafRelativeConstraint(const ZafRelativeConstraint &copy) :
	ZafConstraint(copy),
	ratio(copy.ratio), type(copy.type), stretch(copy.stretch),
	oppositeSide(copy.oppositeSide), center(copy.center)
{
}

ZafRelativeConstraint::~ZafRelativeConstraint(void)
{
}

ZafConstraint *ZafRelativeConstraint::Duplicate(void)
{
	// Initialize ZafConstraint stuff.
	ZafConstraint::Duplicate();
	return (new ZafRelativeConstraint(*this));
}

ZafEventType ZafRelativeConstraint::Event(const ZafEventStruct &event)
{
	// Check for zinc events.
	ZafEventType ccode = event.type;
	if (ccode == S_INITIALIZE)
	{
		ZafConstraint::Event(event);
		return (ccode);
	}
	else if (ccode != S_COMPUTE_SIZE || !object || !object->display)
		return (S_ERROR);

	// Determine support variables.
	ZafRegionStruct objectRegion = object->Region();
	int width = objectRegion.Width();
	int height = objectRegion.Height();
	if (height == 0)
		height = object->display->cellHeight;

	// Get the reference region.
	ZafRegionStruct refRegion;
//	refRegion = object->parent->MaxRegion(parent);
	refRegion = object->parent->MaxRegion(object->parent);
	refRegion.right -= refRegion.left;
	refRegion.bottom -= refRegion.top;
	refRegion.left = refRegion.top = 0;

	// Determine the object region based on the type of connection.
	ZafRegionStruct newRegion = objectRegion;
	if (type == ZAF_RLCF_LEFT)
	{
		if (oppositeSide)
			newRegion.left = (int)(refRegion.right - refRegion.Width() * (unsigned long)ratio / 100);
		else
			newRegion.left = (int)(refRegion.left + refRegion.Width() * (unsigned long)ratio / 100);
		if (center)
			newRegion.left -= width / 2;
		if (!stretch)
			newRegion.right = newRegion.left + width - 1;
	}
	else if (type == ZAF_RLCF_TOP)
	{
		if (oppositeSide)
			newRegion.top = (int)(refRegion.bottom - refRegion.Height() * (unsigned long)ratio / 100);
		else
			newRegion.top = (int)(refRegion.top + refRegion.Height() * (unsigned long)ratio / 100);
		if (center)
			newRegion.top -= height / 2;
		if (!stretch)
			newRegion.bottom = newRegion.top + height - 1;
	}
	else if (type == ZAF_RLCF_RIGHT)
	{
		if (oppositeSide)
			newRegion.right = (int)(refRegion.left + refRegion.Width() * (unsigned long)ratio / 100);
		else
			newRegion.right = (int)(refRegion.right - refRegion.Width() * (unsigned long)ratio / 100);
		if (center)
			newRegion.right += width / 2;
		if (!stretch)
			newRegion.left = newRegion.right - width + 1;
	}
	else if (type == ZAF_RLCF_BOTTOM)
	{
		if (oppositeSide)
			newRegion.bottom = (int)(refRegion.top + refRegion.Height() * (unsigned long)ratio / 100);
		else
			newRegion.bottom = (int)(refRegion.bottom - refRegion.Height() * (unsigned long)ratio / 100);
		if (center)
			newRegion.bottom += height / 2;
		if (!stretch)
			newRegion.top = newRegion.bottom - height + 1;
	}
	object->SetRegion(newRegion);

	// Return the control code.
	return (ccode);
}

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

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

// ----- Attributes ---------------------------------------------------------

int ZafRelativeConstraint::SetCenter(bool tCenter)
{
	center = tCenter;
	return (center);
}

bool ZafRelativeConstraint::SetOppositeSide(bool tOppositeSide)
{
	oppositeSide = tOppositeSide;
	return (oppositeSide);
}

int ZafRelativeConstraint::SetRatio(int tRatio)
{
	ratio = tRatio;
	return (ratio);
}

bool ZafRelativeConstraint::SetStretch(bool tStretch)
{
	stretch = tStretch;
	return (stretch);
}

ZafRelativeConstraintType ZafRelativeConstraint::SetType(ZafRelativeConstraintType tType)
{
	type = tType;
	return (type);
}
	
// ----- Persistent functions -----------------------------------------------
#if defined(USE_ZAF_PERSISTENCE)
ZafRelativeConstraint::ZafRelativeConstraint(const ZafIChar *name, ZafObjectPersistence &persist) :
	ZafConstraint(name, persist.PushLevel(className, classID, ZAF_PERSIST_FILE))
{
	// Read the data.
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafRelativeConstraint::ReadData(persist);
	persist.PopLevel();
}

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

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

	// Read the constraint information.
	ZafUInt16 flag1;
	*file >> ratio >> flag1;
	type = (ZafRelativeConstraintType)(((int)flag1 & 0xF000) >> 12);
	stretch = (flag1 & 0x0001) ? true : false;
	oppositeSide = (flag1 & 0x0002) ? true : false;
	center = (flag1 & 0x0004) ? true : false;
}

void ZafRelativeConstraint::Write(ZafObjectPersistence &persist)
{
	// Write the constraint.
	ZafConstraint::Write(persist.PushLevel(className, classID, ZAF_PERSIST_FILE));
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafRelativeConstraint::WriteData(persist);
	persist.PopLevel();
}

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

	// Write the data.
	ZafUInt16 flag1 = 0;
	flag1 |= (ZafUInt16)((type & 0x000F) << 12);
	flag1 |= (ZafUInt16)(stretch ? 0x0001 : 0);
	flag1 |= (ZafUInt16)(oppositeSide ? 0x0002 : 0);
	flag1 |= (ZafUInt16)(center ? 0x0004 : 0);
	*file << ratio << flag1;
}
#endif
