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

#include <z_tbar.hpp>
#include "m_win.hpp"

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

void ZafToolBar::ConvertRegion(ZafRegionStruct &region, ZafCoordinateType newType)
{
	// Defer to the base class.
	ZafWindowObject::ConvertRegion(region, newType);
}

ZafRegionStruct ZafToolBar::ConvertToOSRegion(const ZafWindowObject *object,
	const ZafRegionStruct *region) const
{
	// Collapse all objects in by two pixels.
	ZafRegionStruct newRegion = ZafWindowObject::ConvertToOSRegion(object, region);
	newRegion -= ZAF_BORDER_SIZE;
	return (newRegion);
}

ZafRegionStruct ZafToolBar::ConvertToZafRegion(const ZafWindowObject *object,
	const ZafRegionStruct *region) const
{
	// Expand all objects out by two pixels.
	ZafRegionStruct newRegion = ZafWindowObject::ConvertToOSRegion(object, region);
	newRegion += ZAF_BORDER_SIZE;
	return (newRegion);
}

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafToolBar::Draw(const ZafEventStruct &event, ZafEventType ccode)
{
	// Check for draw errors.
	if (!screenID)
		return (S_ERROR);

	// Compute the actual draw region.
//	ZafRegionStruct drawRegion = BeginDraw();
	
	// Draw the list items that appear on the screen.
	for (ZafWindowObject *object = First(); object; object = object->Next())
	{
		// Adjust the region so surrounding areas do not get drawn for
		// a focus change.
		ZafRegionStruct region = object->zafRegion;
		region -= ZAF_BORDER_SIZE + 1;

		// Draw the item.
		if (ccode == E_MOTIF && region.Overlap(event.region) && object->Visible())
 		{
			display->SetClipRegion(object->zafRegion);
			object->Draw(event, object->Focus() ? S_CURRENT : S_NON_CURRENT);
		}
	}

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

ZafEventType ZafToolBar::DrawBorder(ZafRegionStruct &, ZafEventType )
{
	// Toolbar does not draw the border.
	return (S_ERROR);
}

ZafEventType ZafToolBar::DrawFocus(ZafRegionStruct &region, ZafEventType )
{
	// Window does not draw a focus rectangle, but must adjust the child 
	// region so it does not clear over an adjoining object.
	region -= ZAF_BORDER_SIZE;
	return (S_ERROR);
}
#endif

ZafEventType ZafToolBar::Event(const ZafEventStruct &event)
{
	// Check for zinc events.
	ZafWindowObject *object;
	ZafEventType ccode = event.type;
	switch (ccode)
	{
	// ----- Create messages -----
	case S_REDISPLAY:
		// Recompute the object regions then call the base class.
		Event(N_SIZE);
		ccode = ZafWindow::Event(event);
		break;

	case S_REGISTER_OBJECT:
		oldRegion.Assign(0, 0, 0, 0);
		// Register the object.
		RegisterObject();

		// Check for a non-current object.
		if (Noncurrent())
		{
			// Add the support objects.  This is primarily for the scroll-bars
			// that must be attached using the XmNverticalScrollBar and 
			// XmNhorizontalScrollBar arguments.
			for (object = SupportFirst(); object; object = object->Next())
				object->Event(event);

			// Create, then remove the highlight from the object.
			for (object = First(); object; object = object->Next())
			{
				object->Event(event);
				XtVaSetValues(object->screenID, XmNhighlightThickness, 0, 0);
			}
		}
		else
			BroadcastEvent(event);
		break;

	// ----- Position & Size messages -----
	case N_SIZE:
		// Notify the children of a size change.
		BroadcastEvent(event);

		// Change the child position.
		for (object = First(); object; object = object->Next())
			object->OSSize();
		break;

	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);
			if (dockType == ZAF_DOCK_LEFT)
				zafRegion.right = zafRegion.left + width + 2 * ZAF_BORDER_SIZE;
			else
				zafRegion.left = zafRegion.right - width - 2 * ZAF_BORDER_SIZE;
		}
		else if (dockType == ZAF_DOCK_TOP || dockType == ZAF_DOCK_BOTTOM)
		{
			int height = zafRegion.bottom - zafRegion.top;
			ZafWindowObject::Event(event);
			if (dockType == ZAF_DOCK_TOP)
				zafRegion.bottom = zafRegion.top + height + 2 * ZAF_BORDER_SIZE;
			else
				zafRegion.top = zafRegion.bottom - height - 2 * ZAF_BORDER_SIZE;
		}

		// 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())
		{
			ZafRegionStruct objectRegion = zafRegion;
			int height = 0, width = 0;
			int column = 0, line = 0;
			if (dockType == ZAF_DOCK_TOP || dockType == ZAF_DOCK_BOTTOM)
			{
				// Determine the appropriate object height.
				for (object = First(); object; object = object->Next())
				{
					ZafRegionStruct region = object->zafRegion;
					if (region.Height() > height)
						height = region.Height();
				}

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

					// Compute the child position.
					objectRegion.left = column;
					objectRegion.top = line;
					objectRegion.right = column + width - 1;
					objectRegion.bottom = line + height - 1;
					object->SetRegion(objectRegion);
					column += width - 1 - ZAF_BORDER_SIZE;
				}

				// Determine the final tool-bar position.
				if (!height)
					height = display->cellHeight - display->preSpace - display->postSpace;
				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)
			{
				// Determine the appropriate object width.
				for (object = First(); object; object = object->Next())
				{
					ZafRegionStruct region = object->zafRegion;
					if (region.Width() > width)
						width = region.Width();
				}

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

					// Compute the child position.
					objectRegion.left = column;
					objectRegion.top = line;
					objectRegion.right = column + width - 1;
					objectRegion.bottom = line + height - 1;
					object->SetRegion(objectRegion);
					line += height - 1 - ZAF_BORDER_SIZE;
				}

				// Determine the final tool-bar position.
				if (!width)
					width = display->cellHeight - display->preSpace - display->postSpace;
				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 L_BEGIN_SELECT:
		for (object = First(); object; object = object->Next())
			if (object->zafRegion.Overlap(event.position))
			{
				object->SetFocus(true);
				ccode = object->Event(event);
				break;
			}
			break;

	case L_CONTINUE_SELECT:
	case L_END_SELECT:
		if (current)
			ccode = Current()->Event(event);
		break;

	// ----- Default operation -----
	default:
		ccode = ZafWindow::Event(event);
		break;
	}

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

ZafRegionStruct ZafToolBar::MaxRegion(ZafWindowObject *object, ZafVtJustify vWeight, ZafHzJustify hWeight)
{
	// Defer to the base class.
	return (ZafWindow::MaxRegion(object, vWeight, hWeight));
}

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

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

void ZafToolBar::OSMapPalette(ZafPaletteStruct &palette, ZafPaletteType type, ZafPaletteState state)
{
	// Defer to the base class.
	ZafWindow::OSMapPalette(palette, type, state);
}

void ZafToolBar::OSRegisterObject(void)
{
	// Defer to the base class.
	ZafWindow::OSRegisterObject();

	// Set additional default values.
	MtfWindowFrame *mtfFrame = MtfWindowFrame::GetMotifWidget(OSScreenID(ZAF_FRAMEID));
	Shadow_Type((Widget)mtfFrame) = XmSHADOW_ETCHED_IN;
}

void ZafToolBar::OSSize(void)
{
	// Default to the base window object class.
	ZafWindowObject::OSSize();
}

OSWindowID ZafToolBar::OSScreenID(ZafScreenIDType type) const
{
	// Defer to the base class.
	return (ZafWindow::OSScreenID(type));
}

