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

#include <z_string.hpp>
#include <z_tbar.hpp>

// ----- ZafToolBar -------------------------------------------------------

void ZafToolBar::ConvertRegion(ZafRegionStruct &region, ZafCoordinateType newType)
{
	if (newType == region.coordinateType)
		return;

	if (Bordered() && newType == ZAF_CELL)
		region.bottom += (int)display->ConvertYValue(ZAF_BORDER_SIZE, ZAF_PIXEL, region.coordinateType);

	ZafWindowObject::ConvertRegion(region, newType);

	if (Bordered() && coordinateType == ZAF_CELL)
		region.bottom -= (int)display->ConvertYValue(ZAF_BORDER_SIZE, ZAF_PIXEL, newType);
}

ZafRegionStruct ZafToolBar::ConvertToOSRegion(const ZafWindowObject *object,
	const ZafRegionStruct *region) const
{
	return (ZafWindow::ConvertToOSRegion(object, region));
}

ZafRegionStruct ZafToolBar::ConvertToZafRegion(const ZafWindowObject *object,
	const ZafRegionStruct *region) const
{
	return (ZafWindow::ConvertToOSRegion(object, region));
}

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafToolBar::Draw(const ZafEventStruct &event, ZafEventType ccode)
{
	return (ZafWindow::Draw(event, ccode));
}

ZafEventType ZafToolBar::DrawBorder(ZafRegionStruct &region, ZafEventType ccode)
{
	ZafPaletteStruct lightShadow = LogicalPalette(ZAF_PM_LIGHT_SHADOW, 0);
	ZafPaletteStruct darkShadow = LogicalPalette(ZAF_PM_DARK_SHADOW, 0);
	ZafPaletteStruct whiteShadow = lightShadow;

	// Copy the background colors to the foreground since display->Line() uses 
	// the foreground color.  The "shadow" palettes have different colors in 
	// the foreground and background entries so they can generate two shades
	// of shadow.
	whiteShadow.colorForeground = whiteShadow.colorBackground;

	// Draw separator.
	if (dockType == ZAF_DOCK_TOP || dockType == ZAF_DOCK_BOTTOM)
	{
		int left = 0;
		int right = zafRegion.right - zafRegion.left;
		int line = (dockType == ZAF_DOCK_TOP ? zafRegion.bottom - zafRegion.top :
			2 * ZAF_BORDER_SIZE - 1);
			
		display->SetPalette(lightShadow);
		display->Line(left, line, right, line);
		display->Line(left, line - 3, right, line - 3);

		display->SetPalette(whiteShadow);
		display->Line(left, line - 1, right, line - 1);

		display->SetPalette(darkShadow);
		display->Line(left, line - 2, right, line - 2);

		if (dockType == ZAF_DOCK_TOP)
			region.bottom -= 2 * ZAF_BORDER_SIZE;
		else
			region.top += 2 * ZAF_BORDER_SIZE;
	}
	else if (dockType == ZAF_DOCK_LEFT || dockType == ZAF_DOCK_RIGHT)
	{
		int top = 0;
		int bottom = zafRegion.bottom - zafRegion.top;
		int column = (dockType == ZAF_DOCK_LEFT ? zafRegion.right - zafRegion.left :
			2 * ZAF_BORDER_SIZE - 1);

		display->SetPalette(lightShadow);
		display->Line(column, top, column, bottom);
		display->Line(column - 3, top, column - 3, bottom);

		display->SetPalette(whiteShadow);
		display->Line(column - 1, top, column - 1, bottom);

		display->SetPalette(darkShadow);
		display->Line(column - 2, top, column - 2, bottom);

		if (dockType == ZAF_DOCK_LEFT)
			region.right -= 2 * ZAF_BORDER_SIZE;
		else
			region.left += 2 * ZAF_BORDER_SIZE;
	}

	return (ccode);
}

ZafEventType ZafToolBar::DrawFocus(ZafRegionStruct &, ZafEventType ccode)
{
	// Don't draw focus for a tool bar.
	return (ccode);
}
#endif

ZafEventType ZafToolBar::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = LogicalEvent(event);

	// Check for zinc events.
	ZafWindowObject *object;
	switch (ccode)
	{
	// ----- Create messages -----
	case S_COMPUTE_SIZE:
		{
			// Call the base class to get the available region.
			if (WrapChildren())
				ZafWindowObject::Event(event);
			else if (dockType == ZAF_DOCK_LEFT || dockType == ZAF_DOCK_RIGHT)
			{
				int width = zafRegion.right - zafRegion.left;
				ZafWindowObject::Event(event);
				zafRegion.right = zafRegion.left + width;
			}
			else if (dockType == ZAF_DOCK_TOP || dockType == ZAF_DOCK_BOTTOM)
			{
				int height = zafRegion.bottom - zafRegion.top;
				ZafWindowObject::Event(event);
				zafRegion.bottom = zafRegion.top + height;
			}

			// Recompute the size of the children.
			for (object = First(); object; object = object->Next())
				object->Event(event);

			// If the tool-bar wraps its sub-objects, it must adjust the size 
			// of all the objects to be of consistent height. If the tool-bar 
			// does not wrap its sub-objects, use the zafRegion height as the 
			// desired size for the tool-bar.
			if (!WrapChildren())
				break;
			int height = 0, width = 0;
			int column = ZAF_BORDER_SIZE, line = ZAF_BORDER_SIZE;
			if (dockType == ZAF_DOCK_TOP || dockType == ZAF_DOCK_BOTTOM)
			{
				if (first)
				{
					// Determine the appropriate object height.
					for (object = First(); object; object = object->Next())
						if (object->zafRegion.Height() > height)
							height = object->zafRegion.Height();

					// Position the children.
					int totalWidth = zafRegion.right - zafRegion.left - ZAF_BORDER_SIZE;
					for (object = First(); object; object = object->Next())
					{
						// Determine the tool-bar size.
						int width = object->zafRegion.Width();
						if (column > ZAF_BORDER_SIZE && column + width > totalWidth)
						{
							line += height + ZAF_BORDER_SIZE;
							column = ZAF_BORDER_SIZE;
						}

						// Compute the child position.
						object->zafRegion.left = column;
						object->zafRegion.top = line;
						column += width;
						object->zafRegion.right = column - 1;
						object->zafRegion.bottom = line + height - 1;
					}
				}
				else
					height = display->cellHeight;

				// Determine the final tool-bar position.
				if (dockType == ZAF_DOCK_TOP)
					zafRegion.bottom = zafRegion.top + line + height + 2 * ZAF_BORDER_SIZE;
				else
					zafRegion.top = zafRegion.bottom - line - height - 2 * ZAF_BORDER_SIZE;
			}
			else if (dockType == ZAF_DOCK_LEFT || dockType == ZAF_DOCK_RIGHT)
			{
				if (first)
				{
					// Determine the appropriate object width.
					for (object = First(); object; object = object->Next())
						if (object->zafRegion.Width() > width)
							width = object->zafRegion.Width();

					// Position the children.
					int totalHeight = zafRegion.bottom - zafRegion.top - ZAF_BORDER_SIZE;
					for (object = First(); object; object = object->Next())
					{
						// Determine the tool-bar size.
						int height = object->zafRegion.Height();
						if (line > ZAF_BORDER_SIZE && line + height > totalHeight)
						{
							column += width + ZAF_BORDER_SIZE;
							line = ZAF_BORDER_SIZE;
						}

						// Compute the child position.
						object->zafRegion.left = column;
						object->zafRegion.top = line;
						line += height;
						object->zafRegion.right = column + width - 1;
						object->zafRegion.bottom = line - 1;
					}
				}
				else
					width = 3 * display->cellWidth;

				// Determine the final tool-bar position.
				if (dockType == ZAF_DOCK_LEFT)
					zafRegion.right = zafRegion.left + column + width + 2 * ZAF_BORDER_SIZE;
				else
					zafRegion.left = zafRegion.right - column - width - 2 * ZAF_BORDER_SIZE;
			}
		}
		break;

	case N_SIZE:
		{
			// Finalize the sizing operation.  Don't pass S_COMPUTE_SIZE to 
			// children to prevent them from sizing.  We already sized them
			// in S_COMPUTE_SIZE.

			// Perform geometry management based on the new window size.
			ZafWindowObject *geometryManager = GetObject(ZAF_NUMID_GEOMETRY);
			if (geometryManager)
				geometryManager->Event(S_COMPUTE_SIZE);

			for (object = First(); object; object = object->Next())
				object->OSSize();
		}
		break;

	// ----- Unknown or error messages -----
	default:
		ccode = ZafWindow::Event(event);
		break;
	}

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

ZafRegionStruct ZafToolBar::MaxRegion(ZafWindowObject *, ZafVtJustify, ZafHzJustify)
{
	// Set up client region.
	ZafRegionStruct region;
	if (dockType == ZAF_DOCK_TOP)
	{
		region.top = 0;
		region.bottom = zafRegion.bottom - zafRegion.top -
			(bordered ? 2 * ZAF_BORDER_SIZE : 0);
	}
	else if (dockType == ZAF_DOCK_BOTTOM)
	{
		region.top = bordered ? 2 * ZAF_BORDER_SIZE : 0;
		region.bottom = zafRegion.bottom - zafRegion.top;
	}
	else
	{
		region.top = 0;
		region.bottom = zafRegion.bottom - zafRegion.top;
	}

	if (dockType == ZAF_DOCK_LEFT)
	{
		region.left = 0;
		region.right = zafRegion.right - zafRegion.left -
			(bordered ? 2 * ZAF_BORDER_SIZE : 0);
	}
	else if (dockType == ZAF_DOCK_RIGHT)
	{
		region.left = bordered ? 2 * ZAF_BORDER_SIZE : 0;
		region.right = zafRegion.right - zafRegion.left;
	}
	else
	{
		region.left = 0;
		region.right = zafRegion.right - zafRegion.left;
	}
	region.coordinateType = zafRegion.coordinateType;

	return (region);
}

// ----- OS Specific Functions ----------------------------------------------

ZafEventType ZafToolBar::OSEvent(const ZafEventStruct &)
{
	return (S_ERROR);
}

void ZafToolBar::OSMapPalette(ZafPaletteStruct &palette, ZafPaletteType type, ZafPaletteState state)
{
	ZafWindowObject::OSMapPalette(palette, type, state);
}

void ZafToolBar::OSRegisterObject(void)
{
	ZafWindow::OSRegisterObject();
}

OSWindowID ZafToolBar::OSScreenID(ZafScreenIDType) const
{
	return (screenID);
}

void ZafToolBar::OSSize(void)
{
	ZafWindow::OSSize();
}


