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

#include <w_app.hpp>
#include <z_tbar.hpp>

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

void ZafToolBar::ConvertRegion(ZafRegionStruct &region, ZafCoordinateType newType)
{
	if (newType != region.coordinateType)
	{
		int offset = 0;

		// Add space for the border.
		if (Bordered())
			offset += ZAF_BORDER_SIZE;

		if (newType == ZAF_CELL)
			region.bottom -= (int)display->ConvertYValue(offset, ZAF_PIXEL, region.coordinateType);

		ZafWindowObject::ConvertRegion(region, newType);

		if (coordinateType == ZAF_CELL)
			region.bottom += (int)display->ConvertYValue(offset, ZAF_PIXEL, newType);
	}
}

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafToolBar::Draw(const ZafEventStruct &, ZafEventType ccode)
{
	// Begin the drawing operation.
	ZafRegionStruct drawRegion = BeginDraw();

	// Draw a border if specified.
	if (Bordered())
		DrawBorder(drawRegion, ccode);

	// Erase the background.
	DrawBackground(drawRegion, ccode);

	// End the drawing operation.
	EndDraw();

	return ccode;
}

ZafEventType ZafToolBar::DrawBorder(ZafRegionStruct &region, ZafEventType ccode)
{
	if (ccode == S_REDISPLAY || ccode == S_REDISPLAY_REGION)
	{
		ZafPaletteState state = PaletteState();
		if (dockType == ZAF_DOCK_LEFT)
		{
			display->SetPalette(LogicalPalette(ZAF_PM_LIGHT_SHADOW, state));
			display->Line(region.right, region.top, region.right, region.bottom);
			region.right--;
			display->SetPalette(LogicalPalette(ZAF_PM_DARK_SHADOW, state));
			display->Line(region.right, region.top, region.right, region.bottom);
			region.right--;

		}
		else if (dockType == ZAF_DOCK_TOP)
		{
			display->SetPalette(LogicalPalette(ZAF_PM_LIGHT_SHADOW, state));
			display->Line(region.left, region.bottom, region.right, region.bottom);
			region.bottom--;
			display->SetPalette(LogicalPalette(ZAF_PM_DARK_SHADOW, state));
			display->Line(region.left, region.bottom, region.right, region.bottom);
			region.bottom--;
		}
		else if (dockType == ZAF_DOCK_RIGHT)
		{
			display->SetPalette(LogicalPalette(ZAF_PM_DARK_SHADOW, state));
			display->Line(region.left, region.top, region.left, region.bottom);
			region.left++;
			display->SetPalette(LogicalPalette(ZAF_PM_LIGHT_SHADOW, state));
			display->Line(region.left, region.top, region.left, region.bottom);
			region.left++;
		}
		else if (dockType == ZAF_DOCK_BOTTOM)
		{
			display->SetPalette(LogicalPalette(ZAF_PM_DARK_SHADOW, state));
			display->Line(region.left, region.top, region.right, region.top);
			region.top++;
			display->SetPalette(LogicalPalette(ZAF_PM_LIGHT_SHADOW, state));
			display->Line(region.left, region.top, region.right, region.top);
			region.top++;
		}
	}
	else if (dockType == ZAF_DOCK_LEFT)
		region.right -= 2;
	else if (dockType == ZAF_DOCK_TOP)
		region.bottom -= 2;
	else if (dockType == ZAF_DOCK_RIGHT)
		region.left += 2;
	else if (dockType == ZAF_DOCK_BOTTOM)
		region.top += 2;

	return (ccode);
}
#endif

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

	if (ccode == E_OSEVENT)
		return ZafToolBar::OSEvent(event);

	switch (ccode)
	{
	case S_COMPUTE_SIZE:
		{
		// Save the tool bar size.
		int height = zafRegion.Height();
		int width = zafRegion.Width();
		ccode = ZafWindowObject::Event(event);

		// Adjust child positions and calculate new size.
		if (WrapChildren())
		{
			ZafWindowObject *object;
			if (dockType == ZAF_DOCK_TOP || dockType == ZAF_DOCK_BOTTOM)
			{
				if (First())
				{
					// Find the height of the tallest child.
					int childHeight = 1;
					for (object = First(); object; object = object->Next())
					{
						object->Event(event);
						if (childHeight < object->zafRegion.Height())
							childHeight = object->zafRegion.Height();
					}

					// Resize children.
					int left = 2;
					int top = 2 + ((bordered && dockType == ZAF_DOCK_BOTTOM) ? ZAF_BORDER_SIZE : 0);
					for (object = First(); object; object = object->Next())
					{
						int childWidth = object->zafRegion.Width();
						if (left > 0 && left + childWidth > zafRegion.Width() - 2)
						{
							left = 2;
							top += childHeight + 2;
						}

						ZafRegionStruct objectRegion;
						objectRegion.coordinateType = ZAF_PIXEL;
						objectRegion.left = left;
						left += childWidth;
						objectRegion.right = left - 1;
						objectRegion.top = top;
						objectRegion.bottom = top + childHeight - 1;
						object->SetRegion(objectRegion);
					}

					// Adjust the tool bar hieght.
					height = top + childHeight + 2 + (Bordered() ? ZAF_BORDER_SIZE : 0);
				}
				else
					height = display->cellHeight;
			}
			else if (dockType == ZAF_DOCK_LEFT || dockType == ZAF_DOCK_RIGHT)
			{
				if (First())
				{
					// Find the width of the widest child.
					int childWidth = 1;
					for (object = First(); object; object = object->Next())
					{
						object->Event(event);
						if (childWidth < object->zafRegion.Width())
							childWidth = object->zafRegion.Width();
					}

					// Resize children.
					int left = 2 + ((bordered && dockType == ZAF_DOCK_RIGHT) ? ZAF_BORDER_SIZE : 0);
					int top = 2;
					for (object = First(); object; object = object->Next())
					{
						int childHeight = object->zafRegion.Height();
						if (top > 0 && top + childHeight > zafRegion.Height() - 2)
						{
							top = 2;
							left += childWidth + 2;
						}

						ZafRegionStruct objectRegion;
						objectRegion.coordinateType = ZAF_PIXEL;
						objectRegion.left = left;
						objectRegion.right = left + childWidth - 1;
						objectRegion.top = top;
						objectRegion.bottom = top + childHeight - 1;
						top += childHeight;
						object->SetRegion(objectRegion);
					}

					// Adjust the tool bar width.
					width = left + childWidth + 2 + (Bordered() ? ZAF_BORDER_SIZE : 0);
				}
				else
					width = 3 * display->cellWidth;
			}
		}

		// Adjust the tool bar size.
		if (dockType == ZAF_DOCK_TOP)
			zafRegion.bottom = zafRegion.top + height - 1;
		else if (dockType == ZAF_DOCK_BOTTOM)
			zafRegion.top = zafRegion.bottom - height + 1;
		else if (dockType == ZAF_DOCK_LEFT)
			zafRegion.right = zafRegion.left + width - 1;
		else if (dockType == ZAF_DOCK_RIGHT)
			zafRegion.left = zafRegion.right - width + 1;
		}
		break;


	case N_SIZE:
		{
		if (wrapChildren)
		{
			ZafWindowObject *object;
			if ((zafRegion.Width() > event.region.Width() &&
				(dockType == ZAF_DOCK_TOP || dockType == ZAF_DOCK_BOTTOM)) ||
				(zafRegion.Height() > event.region.Height() &&
				(dockType == ZAF_DOCK_LEFT || dockType == ZAF_DOCK_RIGHT)))
					for (object = First(); object; object = object->Next())
						object->OSSize();
			else
				for (object = Last(); object; object = object->Previous())
					object->OSSize();
		}
		else
			ccode = ZafWindow::Event(event);

		if (Bordered())
		{
			// Update the border.
			ZafEventStruct updateEvent(S_REDISPLAY_REGION);
			updateEvent.region.coordinateType = ZAF_PIXEL;

			if (zafRegion.Height() != event.region.Height())
			{
				updateEvent.region.left = 0;
				if (dockType == ZAF_DOCK_TOP)
				{
					updateEvent.region.right = event.region.Width() - 1;
					updateEvent.region.top = event.region.Height() - ZAF_BORDER_SIZE;
					updateEvent.region.bottom = event.region.Height() - 1;
					Event(updateEvent);
					updateEvent.region.right = zafRegion.Width() - 1;
					updateEvent.region.top = zafRegion.Height() - ZAF_BORDER_SIZE;
					updateEvent.region.bottom = zafRegion.Height() - 1;
					Event(updateEvent);
				}
				else if (dockType == ZAF_DOCK_BOTTOM)
				{
					updateEvent.region.right = event.region.Width() - 1;
					updateEvent.region.top = zafRegion.Height() - event.region.Height();
					updateEvent.region.bottom = updateEvent.region.top + ZAF_BORDER_SIZE - 1;
					Event(updateEvent);
					updateEvent.region.right = zafRegion.Width() - 1;
					updateEvent.region.top = 0;
					updateEvent.region.bottom = ZAF_BORDER_SIZE - 1;
					Event(updateEvent);
				}
			}

			if (zafRegion.Width() != event.region.Width())
			{
				updateEvent.region.top = 0;
				if (dockType == ZAF_DOCK_LEFT)
				{
					updateEvent.region.left = event.region.Width() - ZAF_BORDER_SIZE;
					updateEvent.region.right = event.region.Width() - 1;
					updateEvent.region.bottom = event.region.Height() - 1;
					Event(updateEvent);
					updateEvent.region.left = zafRegion.Width() - ZAF_BORDER_SIZE;
					updateEvent.region.right = zafRegion.Width() - 1;
					updateEvent.region.bottom = zafRegion.Height() - 1;
					Event(updateEvent);
				}
				else if (dockType == ZAF_DOCK_RIGHT)
				{
					updateEvent.region.left = zafRegion.Width() - event.region.Width();
					updateEvent.region.right = updateEvent.region.left + ZAF_BORDER_SIZE - 1;
					updateEvent.region.bottom = event.region.Height() - 1;
					Event(updateEvent);
					updateEvent.region.left = 0;
					updateEvent.region.right = ZAF_BORDER_SIZE - 1;
					updateEvent.region.bottom = zafRegion.Height() - 1;
					Event(updateEvent);
				}
			}
		}
		}
		break;

	case L_PREVIOUS:
	case L_NEXT:
		ccode = S_UNKNOWN;
		break;

	default:
		ccode = ZafWindow::Event(event);
		break;
	}

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

ZafRegionStruct ZafToolBar::MaxRegion(ZafWindowObject *, ZafVtJustify, ZafHzJustify)
{
	return zafRegion;
}

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

ZafEventType ZafToolBar::OSEvent(const ZafEventStruct &event)
{
	ZafEventType ccode;

	switch (event.osEvent.message)
	{
	case WM_LBUTTONDOWN:
	case WM_RBUTTONDOWN:
#if defined(ZAF_WIN32)
		SetForegroundWindow(RootObject()->OSScreenID(ZAF_FRAMEID));
#else
		SetActiveWindow(RootObject()->OSScreenID(ZAF_FRAMEID));
#endif
		ccode = ZafWindowObject::Event(event);
		break;

	case WM_PAINT:
	case WM_ERASEBKGND:
		ccode = ZafWindowObject::OSEvent(event);
		break;

	default:
		ccode = ZafWindow::Event(event);
	}

	return (ccode);
}

void ZafToolBar::OSMapPalette(ZafPaletteStruct &palette, ZafPaletteType type, ZafPaletteState state)
{
	if (type == ZAF_PM_BACKGROUND)
	{
		if (palette.colorForeground == ZAF_CLR_DEFAULT && palette.osPalette.colorForeground == 0xFFFFFFFFL)
			palette.osPalette.colorBackground = GetSysColor(COLOR_3DFACE);
		if (palette.colorBackground == ZAF_CLR_DEFAULT && palette.osPalette.colorBackground == 0xFFFFFFFFL)
			palette.osPalette.colorBackground = GetSysColor(COLOR_3DFACE);
	}
	else
		ZafWindow::OSMapPalette(palette, type, state);
}

void ZafToolBar::OSRegisterObject(void)
{
	DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
	if (visible)
		dwStyle |= WS_VISIBLE;
	screenID = ZafMSWindowsApp::CreateSubclassedWindow(this, NULL, dwStyle);
}

// ----- Stubs --------------------------------------------------------------

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::ConvertToZafRegion(object, region));
}

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafToolBar::DrawFocus(ZafRegionStruct &, ZafEventType ccode)
{
	return (ccode);
}
#endif

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

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