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

#include <z_mouse2.hpp>	// Mouse images.
#include <z_status.hpp>

// ----- ZafStatusBar -----------------------------------------------------

void ZafStatusBar::ConvertRegion(ZafRegionStruct &region, ZafCoordinateType newType)
{
#if defined(ZAF_GRAPHICS_MODE)
//	ZafWindowObject::ConvertRegion(region, newType);
	if (newType != region.coordinateType)
	{
		int offset = -display->postSpace;

		// 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);
	}
#elif defined(ZAF_TEXT_MODE)
    ZafWindowObject::ConvertRegion(region, newType);
#endif
}

ZafPositionStruct ZafStatusBar::ConvertToOSPosition(const ZafWindowObject *object,
	const ZafPositionStruct *position) const
{
	ZafPositionStruct osPosition = ZafWindowObject::ConvertToOSPosition(object, position);
#if defined(ZAF_GRAPHICS_MODE)
	if (Bordered() && (!object || object != this))
		osPosition.line += ZAF_BORDER_SIZE;
#endif
	return (osPosition);
}

ZafPositionStruct ZafStatusBar::ConvertToZafPosition(const ZafWindowObject *object,
	const ZafPositionStruct *position) const
{
	ZafPositionStruct zafPosition = ZafWindowObject::ConvertToZafPosition(object, position);
#if defined(ZAF_GRAPHICS_MODE)
	if (Bordered())
		zafPosition.line -= ZAF_BORDER_SIZE;
#endif
	return (zafPosition);
}

/* START BLOCK COMMENT
**	void ZafStatusBar::ConvertRegion(bool absolute)
**	{
**		// See if "zafRegion" has already been converted.
**		if (ConvertedCoordinate())
**			return;
**	
**		ZafWindowObject::ConvertRegion(absolute);
**	
**		// Add space for the tool bar border.
**		if (Bordered() && CoordinateType() == ZAF_CELL)
**			zafRegion.bottom += ZAF_BORDER_SIZE;
**	}
END BLOCK COMMENT */

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafStatusBar::Draw(const ZafEventStruct &event, ZafEventType ccode)
{
	// Compute the actual draw region.
	ZafRegionStruct drawRegion = BeginDraw();

	display->SetClipRegion(event.region);

	DrawBackground(drawRegion, ccode);

	EndDraw();

	// Draw the child objects, since they are !systemObject.
	for (ZafWindowObject *object = First(); object; object = object->Next())
	{
		ZafEventStruct childEvent = event;
		if (object->zafRegion.Overlap(event.region, childEvent.region))
		{
			childEvent.region.HzShift(-object->zafRegion.left);
			childEvent.region.VtShift(-object->zafRegion.top);
			object->Draw(childEvent, ccode);
		}
	}

	return (ccode);
}

ZafEventType ZafStatusBar::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 child's border.  Status bar border drawn in Draw().
	display->SetPalette(darkShadow);
	display->Line(region.left, region.top, region.right - 1, region.top);
	display->Line(region.left, region.top, region.left, region.bottom - 1);

	display->SetPalette(whiteShadow);
	display->Line(region.left, region.bottom, region.right, region.bottom);
	display->Line(region.right, region.top, region.right, region.bottom);

	region--;

	return (ccode);
}

ZafEventType ZafStatusBar::DrawFrame(const ZafEventStruct &event, ZafEventType ccode)
{
	// Compute the actual draw region.
	ZafRegionStruct drawRegion = BeginDrawFrame();

	ZafRegionStruct clip = display->ClipRegion();
	display->SetClipRegion(event.region);
	DrawBackground(drawRegion, ccode);
//	display->SetClipRegion(clip);

	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 border here. ZafStatusBar::DrawBorder() draws the borders of
	// the children.
	if (bordered)
	{
		// Draw separator above status bar.
		display->SetPalette(lightShadow);
		display->Line(0, 0, drawRegion.right, 0);
		display->Line(0, 3, drawRegion.right, 3);

		display->SetPalette(whiteShadow);
		display->Line(0, 2, drawRegion.right, 2);

		display->SetPalette(darkShadow);
		display->Line(0, 1, drawRegion.right, 1);

		drawRegion.top += 2 * ZAF_BORDER_SIZE;
	}

/* START BLOCK COMMENT
**	//	--drawRegion.right;
**		--drawRegion.bottom;
**	
**		display->SetPalette(darkShadow);
**		display->Line(drawRegion.right - 1, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 1);
**		display->Line(drawRegion.right - 2, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 2);
**		display->Line(drawRegion.right - 5, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 5);
**		display->Line(drawRegion.right - 6, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 6);
**		display->Line(drawRegion.right - 9, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 9);
**		display->Line(drawRegion.right - 10, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 10);
**	
**		display->SetPalette(whiteShadow);
**		display->Line(drawRegion.right - 3, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 3);
**		display->Line(drawRegion.right - 7, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 7);
**		display->Line(drawRegion.right - 11, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 11);
**	
**		display->SetPalette(lightShadow);
**		display->Line(drawRegion.right - 4, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 4);
**		display->Line(drawRegion.right - 8, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 8);
**		display->Line(drawRegion.right - 12, drawRegion.bottom, drawRegion.right, drawRegion.bottom - 12);
END BLOCK COMMENT */

	EndDraw();
	return (ccode);
}
#endif

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

	// Check for zinc events.
	switch (ccode)
	{
	// ----- Position & Size messages -----
	case S_COMPUTE_SIZE:
		{
			int height = zafRegion.bottom - zafRegion.top;
			ccode = ZafWindowObject::Event(event);
			zafRegion.top = zafRegion.bottom - height;
		}
		break;

	case S_REGISTER_OBJECT:
		{
			// Register the object.  By registering children here, we prevent them
			// from being labelled as system objects.  This will cause them to
			// get their palettes from the status bar and to let the status bar
			// draw their borders.
			RegisterObject();

			ZafWindowObject *object;
			for (object = SupportFirst(); object; object = object->Next())
				object->Event(event);

			// Define the children to have the same screenID as their parent.
			for (object = First(); object; object = object->Next())
				object->screenID = screenID;
		}
		break;

	case L_VIEW:
	case L_BEGIN_SELECT:
		{
			if (editMode)
			{
				ZafWindowObject::Event(event);
				break;
			}

			ZafRegionStruct sizeGripRegion;
			sizeGripRegion.coordinateType = zafRegion.coordinateType;
			sizeGripRegion.left = clientRegion.right + 1;
			sizeGripRegion.right = zafRegion.Width() - 1;
			sizeGripRegion.bottom = zafRegion.Height() - 1;
			sizeGripRegion.top = sizeGripRegion.bottom - 13; // Sizegrip size.
			ZafWindow *parentWindow = DynamicPtrCast(parent, ZafWindow);
			if (parentWindow->Sizeable() && !parentWindow->Maximized() &&
				sizeGripRegion.Overlap(event.position))
			{
				if (ccode == L_BEGIN_SELECT)
				{
					ZafEventStruct sizeEvent = event;
					sizeEvent.type = S_SIZE_MODE;
					sizeEvent.rawCode = ZAF_SIZE_RIGHT | ZAF_SIZE_BOTTOM;
					parent->Event(sizeEvent);
					windowManager->CaptureMouse(this);
				}
				else
					eventManager->SetDeviceState(E_MOUSE, DM_BOTTOM_RIGHT_CORNER);
			}
			// Suppress mouse clicks on the status bar.
			else if (ccode == L_VIEW)
		 		eventManager->SetDeviceState(E_MOUSE, DM_VIEW);
		}
		break;

	case L_END_SELECT:
	case L_CONTINUE_SELECT:
		if (windowManager->MouseEventRoute() == this)
		{
			if (EditMode())
				ZafWindowObject::Event(event);
			else
			{
				if (ccode == L_END_SELECT)
					windowManager->CaptureMouse(0);
				parent->Modify(event);
			}
		}
		break;

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

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

ZafRegionStruct ZafStatusBar::MaxRegion(ZafWindowObject *, ZafVtJustify, ZafHzJustify)
{
	// Set up client region.
	ZafRegionStruct region;
	region.left = 0;
#if defined(ZAF_GRAPHICS_MODE)
	region.top = bordered ? ZAF_BORDER_SIZE + 1 : 0;
	region.right = zafRegion.Width() - 12 - 1;
#elif defined(ZAF_TEXT_MODE)
	region.top = 0;
	region.right = zafRegion.Width() - 1;
#endif
	region.bottom = zafRegion.Height();
//	region.bottom = zafRegion.Height() - 1;
	region.coordinateType = zafRegion.coordinateType;

	return (region);
}

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

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

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

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

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

void ZafStatusBar::OSSize(void)
{
	// Redraw sizegrip if necessary.  The sizegrip is not an actual object,
	// so it doesn't redraw if the status bar is sized smaller.
	ZafRegionStruct oldRegion = ZafWindowObject::oldRegion;

	ZafWindow::OSSize();

	if (zafRegion.right != oldRegion.right)
	{
		ZafRegionStruct updateRegion = ConvertToDrawRegion(this, &zafRegion);

		updateRegion.left = clientRegion.right + 1;
		OSInvalidateRegion(&updateRegion, false, false);
	}
}

