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

#include <z_icon1.hpp>
#include <z_string.hpp>

// ----- ZafIcon -----------------------------------------------------------

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType ZafIcon::Draw(const ZafEventStruct &event, ZafEventType ccode)
{
	// Don't allow to draw on parent window as if it is a "normal" object.
	// Parent window draws the icon when minimized.
	if (iconType == ZAF_MINIMIZE_ICON)
		return (ccode);

	// Compute the actual draw region.
	ZafPaletteState state = PaletteState();
	ZafRegionStruct drawRegion = BeginDraw();

	display->SetClipRegion(event.region);

	// Don't draw if everything will be clipped.
	if (!drawRegion.Overlap(display->ClipRegion()))
	{
		EndDraw();
		return (ccode);
	}

	if (Bordered())
		DrawBorder(drawRegion, ccode);

	display->SetPalette(LogicalPalette(ZAF_PM_BACKGROUND, state));
	display->Rectangle(drawRegion, 0, true);

	display->SetPalette(LogicalPalette(ZAF_PM_TEXT, state));

	ZafRegionStruct draw = drawRegion;

	const ZafIChar *text = Text();
	if (iconData)
	{
		int width = draw.Width();
		int height = draw.Height();

		int bitmapWidth = iconData->Width();
		int bitmapHeight = iconData->Height();

		int textWidth = 0;
		int textHeight = 0;

		if (text)
		{
			ZafRegionStruct textSize = display->TextSize(text);
			textWidth = textSize.Width();
			textHeight = textSize.Height();
		}

		int totalHeight = bitmapHeight + textHeight;

		if (hzJustify == ZAF_HZ_LEFT)
			;
		else if (hzJustify == ZAF_HZ_CENTER)
			draw.left += width / 2 - bitmapWidth / 2;
		else if (hzJustify == ZAF_HZ_RIGHT)
			draw.left = draw.right - bitmapWidth + 1;

		if (vtJustify == ZAF_VT_TOP)
			;
		else if (vtJustify == ZAF_VT_CENTER && hzJustify == ZAF_HZ_CENTER)
			draw.top += height / 2 - totalHeight / 2;
		else if (vtJustify == ZAF_VT_CENTER)
			draw.top += height / 2 - bitmapHeight / 2;
		else if (vtJustify == ZAF_VT_BOTTOM)
			draw.top = draw.bottom - bitmapHeight;

		display->Icon(draw.left, draw.top, *iconData);

		if (text)
		{
			draw = drawRegion;

			if (hzJustify == ZAF_HZ_LEFT)
				draw.left += bitmapWidth + 1;
			else if (hzJustify == ZAF_HZ_CENTER)
				draw.left += width / 2 - textWidth / 2;
			else if (hzJustify == ZAF_HZ_RIGHT)
				draw.left = draw.right - bitmapWidth - textWidth + 1;

			if (vtJustify == ZAF_VT_TOP)
				draw.top += bitmapHeight + 1;
			else if (vtJustify == ZAF_VT_CENTER && hzJustify == ZAF_HZ_CENTER)
				draw.top += height / 2 - totalHeight / 2 + bitmapHeight + 1;
			else if (vtJustify == ZAF_VT_CENTER)
				draw.top += height / 2 - textHeight / 2;
			else if (vtJustify == ZAF_VT_BOTTOM)
				draw.top = draw.bottom - bitmapHeight - textHeight - 1;

			draw.right = draw.left + textWidth;
			draw.bottom = draw.top + textHeight;

//			display->Text(draw.left, draw.top, draw.right, draw.bottom, text, -1, ZAF_HZ_LEFT, ZAF_VT_TOP, hotKeyIndex, true);
			display->Text(draw.left, draw.top, draw.right, draw.bottom, text, -1, ZAF_HZ_LEFT, ZAF_VT_TOP, hotKeyIndex, false);
		}
	}
	else if (text)
		display->Text(draw.left, draw.top, draw.right, draw.bottom, text, -1, hzJustify, vtJustify, hotKeyIndex, false);
//		display->Text(draw.left, draw.top, draw.right, draw.bottom, text, -1, hzJustify, vtJustify, hotKeyIndex, true);

	// Draw focus.
	if (Focus())
	{
		ZafRegionStruct focusRegion = drawRegion;

		if (text)
		{
			// Assign the rectangle to the region structure.
			ZafRegionStruct textSize = display->TextSize(text);
			int width = textSize.Width();
			int height = textSize.Height();

			int leftText = draw.left;
			if (hzJustify == ZAF_HZ_RIGHT)
				leftText = draw.right - width;
			else if (hzJustify == ZAF_HZ_CENTER)
				leftText = ((draw.right + draw.left) / 2) - (width / 2);
			leftText--;

			int topText = draw.top;
			if (vtJustify == ZAF_VT_BOTTOM)
				topText = draw.bottom - height;
			else if (vtJustify == ZAF_VT_CENTER)
				topText = ((draw.bottom + draw.top) / 2) - (height / 2);

			focusRegion.left = leftText;
			focusRegion.top = topText;
			focusRegion.right = leftText + width;
			focusRegion.bottom = topText + height;
		}

		DrawFocus(focusRegion, ccode);
	}

	EndDraw();

	return (ccode);
}

ZafEventType ZafIcon::DrawFocus(ZafRegionStruct &region, ZafEventType ccode)
{
	if (SystemObject())
		ZafButton::DrawFocus(region, ccode);
	else
	{
		ZafRegionStruct focusRegion = ConvertToDrawRegion(this, &zafRegion);
		return (parent->DrawFocus(focusRegion, ccode));
	}

	return (ccode);
}

ZafEventType ZafIcon::DrawShadow(ZafRegionStruct &, int, ZafEventType ccode)
{
	// Does not have a shadow.
	return (ccode);
}
#endif

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

	// Check for zinc events.
	switch (ccode)
	{
	// ----- Create messages -----
	case S_INITIALIZE:
		ccode = ZafWindowObject::Event(event);
		if (iconType == ZAF_MINIMIZE_ICON)
		{
			SetSelectOnDoubleClick(true);
			SetDisabled(false);
		}
		break;

	case S_COMPUTE_SIZE:
		{
			ZafWindowObject::Event(event);

			if (iconType != ZAF_MINIMIZE_ICON)
			{
				if (Text())
				{
					ZafRegionStruct region;
					display->SetPalette(LogicalPalette(ZAF_PM_TEXT, ZAF_PM_ANY_STATE));
					region = display->TextSize(Text());
					zafRegion.right = zafRegion.left + region.Width() + 1;
					zafRegion.bottom = zafRegion.top + region.Height() + 1;
				}
				else
				{
					zafRegion.right = zafRegion.left;
					zafRegion.bottom = zafRegion.top;
				}

				if (iconData)
				{
					if (vtJustify == ZAF_VT_TOP || vtJustify == ZAF_VT_BOTTOM ||
						(vtJustify == ZAF_VT_CENTER && hzJustify == ZAF_HZ_CENTER))
						zafRegion.bottom += iconData->height + 1;
					else if (zafRegion.Height() < iconData->height)
						zafRegion.bottom = zafRegion.top + iconData->height - 1;

					if (hzJustify == ZAF_HZ_LEFT || hzJustify == ZAF_HZ_RIGHT)
						zafRegion.right += iconData->width - 1;
					else if (zafRegion.Width() < iconData->width)
						zafRegion.right = zafRegion.left + iconData->width - 1;
				}

				zafRegion.bottom += 2 * ZAF_BORDER_SIZE;
				zafRegion.right += 2 * ZAF_BORDER_SIZE;
			}
		}
		break;

	// ----- Actions -----
	case L_DOUBLE_CLICK:
	case L_SELECT:
		if (iconType == ZAF_MINIMIZE_ICON)
		{
			// Close the system menu, which may or may not be displayed.
			windowManager->Event(S_CLOSE_TEMPORARY);
			parent->Event(S_RESTORE);
		}
		else
			ccode = ZafButton::Event(event);
		break;

	case L_BEGIN_SELECT:
	case L_END_SELECT:
		{
			if (iconType != ZAF_MINIMIZE_ICON)
			{
				ccode = ZafButton::Event(event);
				break;
			}

			// Icon is a minimize icon.
			ZafEventStruct mouseEvent = event;

			// The zafRegion of a minimize icon contains the last location
			// for the minimized window, not the icon's actual location.
			// The parent window is responsible for drawing the minimize icon at 
			// (0,0) in the parent's region (which it obtained from the minimize 
			// icon).  Therefore, mouse clicks must be shifted so that 
			// ZafButton::Event() can determine if the mouse click did actually 
			// happen on the icon.
			mouseEvent.position.line += zafRegion.top;
			mouseEvent.position.column += zafRegion.left;

			ZafRegionStruct zeroBasedRegion = ConvertToDrawRegion(this, &zafRegion);

			// Click may have come to the icon simply because it was the current
			// object in the window manager list.  Check to see if the click
			// occurred in the icon region.
			if (!zeroBasedRegion.Overlap(event.position))
				break;

			// If it is a minimize icon, don't let clicks through unless they
			// are actually on the icon or the text.
			ZafRegionStruct imageRegion, textRegion;
#if defined(ZAF_GRAPHICS_MODE)
			imageRegion.coordinateType = ZAF_PIXEL;
#elif defined(ZAF_TEXT_MODE)
			imageRegion.coordinateType = ZAF_CELL;
#endif

			if (iconData)
			{
				imageRegion.left = (zafRegion.Width() - iconData->Width()) / 2;
				imageRegion.top = 0;
				imageRegion.right = imageRegion.left + iconData->Width() - 1;
				imageRegion.bottom = imageRegion.top + iconData->Height() - 1;
			}
			else
			{
				imageRegion.left =
				imageRegion.top =
				imageRegion.right =
				imageRegion.bottom = -1;
			}

			const ZafIChar *text = Text();
			if (text)
			{
				display->SetPalette(LogicalPalette(ZAF_PM_TEXT, ZAF_PM_ANY_STATE));
				ZafRegionStruct textSize = display->TextSize(text);
				int width = textSize.Width();
				int height = textSize.Height();
				textRegion.left = (zafRegion.Width() - width) / 2;
				textRegion.right = textRegion.left + width - 1;
				textRegion.bottom = zafRegion.Height() - 1;
				textRegion.top = textRegion.bottom - height + 1;
				textRegion.coordinateType = textSize.coordinateType;
			}
			else
				textRegion = imageRegion;

			if (!imageRegion.Overlap(event.position) && !textRegion.Overlap(event.position))
				break;

			// Let button process first so can process for double-click, etc.
			ccode = ZafButton::Event(mouseEvent);

			// Keep track of where the icon was when passing the begin select
			// to the parent window as an S_MOVE_MODE.  If the icon gets moved, then
			// don't put up the system menu.  If the icon is not moved, display
			// the system menu on the release.
			static ZafRegionStruct lastRegion = zafRegion;
			if (ccode == L_BEGIN_SELECT)
			{
				lastRegion = zafRegion;
				parent->Event(ZafEventStruct(S_MOVE_MODE, 0x0001, event.position));
			}
			else if (lastRegion == zafRegion && ccode != L_DOUBLE_CLICK)
				parent->Event(L_SYSTEM_MENU);
		}
		break;

	case S_COPY_DATA:
		{
			ZafIcon *icon = DynamicPtrCast(event.windowObject, ZafIcon);
			if (!icon)
				break;

			iconData->SetIcon(*icon->IconData());
		}
		break;

	case S_SET_DATA:
		{
			if (event.windowObject)
			{
				ZafIcon *icon = DynamicPtrCast(event.windowObject, ZafIcon);
				if (!icon)
					break;

				SetIconData(icon->IconData());
			}
			else
				SetIconData(new ZafIconData(*iconData));
		}
		break;

	case S_REDISPLAY_REGION:
	case S_REDISPLAY:
		// Parent window redraws the minIcon when necessary.
		if (iconType == ZAF_MINIMIZE_ICON)
			break;

		// Fall through to default case.

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

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

// ----- Attributes ---------------------------------------------------------

bool ZafIcon::SetDisabled(bool setDisabled)
{
	ZafWindowObject::SetDisabled(setDisabled);
//	RedisplayData();
	return (disabled);
}

bool ZafIcon::SetSelected(bool tSelected)
{
	return (ZafButton::SetSelected(tSelected));
}

bool ZafIcon::SetVisible(bool tVisible)
{
	return (ZafButton::SetVisible(tVisible));
}

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

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

void ZafIcon::OSRegisterObject(void)
{
	ZafWindowObject::OSRegisterObject();
}

ZafError ZafIcon::OSSetImage(void)
{
	if (screenID)
		Event(S_REDISPLAY);
	return (ZAF_ERROR_NONE);
}

ZafError ZafIcon::OSSetText(void)
{
	if (screenID)
		Event(S_REDISPLAY);
	return (ZAF_ERROR_NONE);
}

void ZafIcon::OSSize(void)
{
	ZafButton::OSSize();
}

ZafError ZafIcon::OSUpdatePalettes(ZafPaletteType , ZafPaletteType )
{
	if (screenID)
	{
		Event(ZafEventStruct(S_COMPUTE_SIZE));
		OSSize();
		Redisplay();
	}

	return (ZAF_ERROR_NONE);
}
