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

#include <z_border.hpp>
#include "m_win.hpp"
#include "m_utils.hpp"

// ----- ZafBorder ----------------------------------------------------------

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafBorder::Draw(const ZafEventStruct &, ZafEventType ccode)
{
	// Check for a valid sub-window.
	if (!screenID || !SystemObject() || zafRegion.top < 0)
		return (S_ERROR);

	// Compute the actual draw region.
	MtfWindowFrame *mtfFrame = MtfWindowFrame::GetMotifWidget(screenID);
	ZafRegionStruct drawRegion;
	drawRegion.left = 0;
	drawRegion.top = 0;
	drawRegion.right = mtfFrame->core.width - 1;
	drawRegion.bottom = mtfFrame->core.height - 1;

	// Get the color palettes.
	parent->BeginDraw();
	ZafPaletteState state = PaletteState();
	ZafPaletteStruct topShadow = LogicalPalette(ZAF_PM_LIGHT_SHADOW, state);
	if ((display->DisplayMode() == ZAF_DISPLAY_MONO && 
	  topShadow.monoBackground < ZAF_MAXCOLORS) || 
	  (display->DisplayMode() != ZAF_DISPLAY_MONO 
	  && topShadow.colorBackground < ZAF_MAXCOLORS))
	{
		XGCValues values;
		if (display->DisplayMode() == ZAF_DISPLAY_MONO)
			values.background = ((ZafScreenDisplay *)display)->monoTable[topShadow.monoBackground].pixel;
		else
			values.background = ((ZafScreenDisplay *)display)->colorTable[topShadow.colorBackground].pixel;
		values.foreground = values.background;
		topShadow.osPalette = XtGetGC((Widget)mtfFrame, GCForeground | GCBackground, &values);
	}
	ZafPaletteStruct bottomShadow = LogicalPalette(ZAF_PM_DARK_SHADOW, state);
	if ((display->DisplayMode() == ZAF_DISPLAY_MONO && 
	  bottomShadow.monoBackground < ZAF_MAXCOLORS) ||
		(display->DisplayMode() != ZAF_DISPLAY_MONO 
		&& bottomShadow.colorBackground < ZAF_MAXCOLORS))
	{
		XGCValues values;
		if (display->DisplayMode() == ZAF_DISPLAY_MONO)
			values.background = ((ZafScreenDisplay *)display)->monoTable[bottomShadow.monoBackground].pixel;
		else
			values.background = ((ZafScreenDisplay *)display)->colorTable[bottomShadow.colorBackground].pixel;
		values.foreground = values.background;
		bottomShadow.osPalette = XtGetGC((Widget)mtfFrame, GCForeground | GCBackground, &values);
	}

	// Draw the shadow in the parent's frame area.
	_XmDrawShadows(XtDisplay(mtfFrame), XtWindow(mtfFrame),
		topShadow.osPalette, bottomShadow.osPalette,
		drawRegion.left, drawRegion.top, drawRegion.Width(),
		drawRegion.Height(), ZAF_SHADOW_SIZE, XmSHADOW_OUT);

	drawRegion -= ZAF_SHADOW_SIZE;
	display->SetPalette(LogicalPalette(ZAF_PM_BACKGROUND, state));
	for (int i = ZAF_SHADOW_SIZE; i < width; i++)
	{
		XDrawRectangle(XtDisplay(mtfFrame), XtWindow(mtfFrame),
			((ZafScreenDisplay *)display)->xGC, drawRegion.left,
			drawRegion.top, drawRegion.right - drawRegion.left,
			drawRegion.bottom - drawRegion.top);
		drawRegion--;
	}

	_XmDrawShadows(XtDisplay(mtfFrame), XtWindow(mtfFrame),
		topShadow.osPalette, bottomShadow.osPalette,
		drawRegion.left, drawRegion.top, drawRegion.Width(),
		drawRegion.Height(), 1, XmSHADOW_IN);
	parent->EndDraw();

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

ZafEventType ZafBorder::Event(const ZafEventStruct &event)
{
	// Check for special MDI code.
	ZafEventType ccode = event.type;
	if (SystemObject())
	{
		switch (ccode)
		{
		// ----- Create messages -----
		case S_INITIALIZE:
			ZafWindowObject::Event(event);
			break;

		case S_COMPUTE_SIZE:
			// This widget will be in the motif frame, not in the client area.
			ZafWindowObject::Event(event);
			if (DynamicPtrCast(parent, ZafWindow)->Maximized())
				zafRegion++;
			else
				zafRegion -= width;
			break;

		case S_REGISTER_OBJECT:
			screenID = parent->OSScreenID(ZAF_FRAMEID);
			break;

		// ----- Activation messages -----
		case S_REDISPLAY:
			ccode = ZafWindowObject::Event(event);
			break;

		// ----- Motif or unknown messages -----
		case E_MOTIF:
			ccode = ZafWindowObject::Event(event);
			break;

		default:
			return (S_UNKNOWN);
		}

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

	// Check for zinc events.
	switch (ccode)
	{
	// ----- Create messages -----
	case S_INITIALIZE:
		// Set the parent decorations.
		if (parent && !parent->parent)
			DynamicPtrCast(parent, ZafWindow)->SetDecoration(MWM_DECOR_BORDER);
		break;

	case S_DEINITIALIZE:
		// Clear the parent decorations.
		if (parent && !parent->parent)
			DynamicPtrCast(parent, ZafWindow)->ClearDecoration(MWM_DECOR_BORDER);
		break;

	case S_COMPUTE_SIZE:
		// This widget will be in the motif frame, not in the client area.
		zafRegion.Assign(-1, -1, -1, -1, ZAF_PIXEL);
		break;

	// ----- Motif or unknown messages -----
	case E_MOTIF:
		ccode = ZafWindowObject::Event(event);
		break;

	default:
		return (S_UNKNOWN);
	}

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

void ZafBorder::GetClip(ZafWindowObject *object, ZafRegionStruct &clip, ZafRegionStruct &virtualRegion)
{
	// Defer to the base class.
	ZafWindowObject::GetClip(object, clip, virtualRegion);
}

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

ZafError ZafBorder::OSGetWidth(void)
{
	return (ZAF_ERROR_NONE);
}

void ZafBorder::OSMapPalette(ZafPaletteStruct &palette, ZafPaletteType type, ZafPaletteState state)
{
	// Defer to the parent class.
	if (screenID)
		parent->OSMapPalette(palette, type, state);
}

void ZafBorder::OSRegisterObject(void)
{
	// Border is not registered, even if it is a system object.
}

ZafError ZafBorder::OSSetWidth(void)
{
	return (ZAF_ERROR_NONE);
}

void ZafBorder::OSSize(void)
{
	// Border does not need to be sized.
}

ZafError ZafBorder::OSUpdatePalettes(ZafPaletteType zafTypes, ZafPaletteType osTypes)
{
	// Skip the button level.
	return (ZafWindowObject::OSUpdatePalettes(zafTypes, osTypes));
}

