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

#include <time.h>
#include <z_button.hpp>
#include <z_ctype.hpp>
#define USE_RAW_KEYS
#include <z_keymap.hpp>
#include <z_string.hpp>
#include <z_timer.hpp>
#include <z_utils.hpp>

#define ZAF_BUTTON_INFO
#include "img_def.cpp"

// ----- ZafButton ---------------------------------------------------------

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

	display->SetClipRegion(event.region);

	ZafWindow *root = DynamicPtrCast(RootObject(), ZafWindow);
	bool defaultButton = (focus || (root->DefaultButton(true) == this &&
		root->DefaultButton(false) == this));

	// Draw check boxes and radio buttons.
	if (ButtonType() == ZAF_CHECK_BOX || ButtonType() == ZAF_RADIO_BUTTON)
	{
		state &= ~ZAF_PM_SELECTED;

		// Erase the background.
		// (Background palette doesn't affect radio buttons and check boxes.)
		//??? A better way is needed... maybe pass state parameter with draw functions.
		bool saveSelected = selected;
		selected = false;
		DrawBackground(drawRegion, ccode);
		selected = saveSelected;

		// Set the text palette.
		ZafPaletteStruct textPalette = LogicalPalette(ZAF_PM_TEXT, state);
		display->SetPalette(textPalette);

		// Compute regions.
		ZafRegionStruct textRegion;
		if (stringData)
			textRegion = display->TextSize(*stringData);
		else
		{
			textRegion.coordinateType = ZAF_PIXEL;
			textRegion.left = textRegion.top = 1;
			textRegion.right = textRegion.bottom = 0;
		}
		ZafRegionStruct imageRegion;
		imageRegion.coordinateType = ZAF_PIXEL;
		imageRegion.left = imageRegion.top = 1;
		imageRegion.right = checkBitmap->width;
		imageRegion.bottom = checkBitmap->height;
		ComputeDrawRegions(drawRegion, imageRegion, textRegion, 4);

		// Draw the check or radio bitmap.
/* START BLOCK COMMENT
**			if (ButtonType() == ZAF_RADIO_BUTTON)
**				display->Bitmap(imageRegion.left, imageRegion.top, selected ?
**					(depressed ? *radioSelectedDepressedBitmap : *radioSelectedBitmap) :
**					(depressed ? *radioDepressedBitmap : *radioBitmap));
**			else
**				display->Bitmap(imageRegion.left, imageRegion.top, selected ?
**					(depressed ? *checkSelectedDepressedBitmap : *checkSelectedBitmap) :
**					(depressed ? *checkDepressedBitmap : *checkBitmap));
END BLOCK COMMENT */
		if (ButtonType() == ZAF_RADIO_BUTTON)
			display->Bitmap(imageRegion.left, imageRegion.top, selected ?
				*radioSelectedBitmap : *radioBitmap);
		else
			display->Bitmap(imageRegion.left, imageRegion.top, selected ?
				*checkSelectedBitmap : *checkBitmap);

		// Draw the focus. 
		if (Focus())
			DrawFocus(textRegion, ccode);

		// Draw the text.
		if (stringData && (ccode == S_REDISPLAY || ccode == S_REDISPLAY_DATA ||
			ccode == S_REDISPLAY_REGION || ccode == L_SELECT))
		{
/* START BLOCK COMMENT
**				if (Disabled())
**				{
**					display->SetPalette(textPalette);
**	
**					// If disabled, chisel color is in palette background.
**					display->SetForeground(textPalette.colorBackground);
**					display->Text(textRegion.left + 1, textRegion.top + 1, textRegion.right + 1,
**						textRegion.bottom + 1, *stringData, -1, ZAF_HZ_CENTER, ZAF_VT_CENTER, hotKeyIndex, false);
**				}
END BLOCK COMMENT */

			display->SetPalette(textPalette);
			display->Text(textRegion, *stringData, -1, ZAF_HZ_CENTER, ZAF_VT_CENTER, hotKeyIndex, false);
		}

		// End the drawing operation.
		EndDraw();
		return (ccode);
	}

	// Draw "normal" buttons.  (Not check boxes or radio buttons.)
	if (ccode == L_SELECT)
	{
		if (ButtonType() != ZAF_FLAT_BUTTON)
		{
			// Draw the border/default button indicator.
			if (bordered || focus || defaultButton)
				DrawBorder(drawRegion, ccode);

			// Compute the focus region before the shadow is drawn, since the
			// shadow may be a different depth when the button is depressed.
			ZafRegionStruct focusRegion = drawRegion;
			focusRegion -= (depth + 1);

			// Draw the shadow.
			if (allowToggling && selected && !depressed)
				DrawShadow(drawRegion, -depth, ccode);
			else
				DrawShadow(drawRegion, depressed ? -1 : depth, ccode);

			// Erase focus rect.
			if (focus)
			{
				DrawFocus(focusRegion, S_REDISPLAY);
				focusRegion += (depth + 1);
			}

			// BitBlt button contents.
			if (depressed)
			{
				drawRegion.right--;
				drawRegion.bottom--;
				display->RegionCopy(drawRegion, drawRegion.left + 1, drawRegion.top + 1);
			}
			else
			{
				drawRegion.left++;
				drawRegion.top++;
				display->RegionCopy(drawRegion, drawRegion.left - 1, drawRegion.top - 1);
				display->Line(drawRegion.left, drawRegion.bottom, drawRegion.right, drawRegion.bottom);
				display->Line(drawRegion.right, drawRegion.bottom - 1, drawRegion.right, drawRegion.top);
			}

			// Restore focus rect.
			if (focus)
				DrawFocus(focusRegion, S_REDISPLAY);

			// Erase old bitblt position.
			display->SetPalette(LogicalPalette(ZAF_PM_BACKGROUND, state));
			if (depressed)
			{
				display->Line(drawRegion.left, drawRegion.top, drawRegion.left, drawRegion.bottom);
				display->Line(drawRegion.left + 1, drawRegion.top, drawRegion.right, drawRegion.top);
			}
			else
			{
				display->Line(drawRegion.left, drawRegion.bottom, drawRegion.right, drawRegion.bottom);
				display->Line(drawRegion.right, drawRegion.bottom - 1, drawRegion.right, drawRegion.top);
			}

		}

		// Only the depressed state needed to be updated.
		EndDraw();
		return (ccode);
	}

//??? Optimization.
//	if (ccode == S_SHOW_DEFAULT || ccode == S_HIDE_DEFAULT)
//	{
//		if (ccode == S_SHOW_DEFAULT)
//		{
//			DrawBorder(drawRegion, S_REDISPLAY);
//			if (ButtonType() != ZAF_FLAT_BUTTON)
//				DrawShadow(drawRegion, depressed ? -depth : depth, S_REDISPLAY);
//		}
//		else
//		{
//			if (ButtonType() != ZAF_FLAT_BUTTON)
//				DrawShadow(drawRegion, depressed ? -depth : depth, S_REDISPLAY);
//			display->SetPalette(LogicalPalette(ZAF_PM_BACKGROUND, state));
//			display->Rectangle(drawRegion, 1);
//		}
//
//		// Only the default state needed to be updated.
//		EndDraw();
//		return (ccode);
//	}

	// Draw a one pixel border.
	if (defaultButton || Focus() || Bordered())
		DrawBorder(drawRegion, ccode);

	// Compute the focus region before the shadow is drawn, since the
	// shadow may be a different depth when the button is depressed.
	ZafRegionStruct focusRegion = drawRegion;
	focusRegion -= depth;

	// Draw the 3D shadow.
	if (ButtonType() != ZAF_FLAT_BUTTON)
	{
		if (allowToggling && selected && !depressed)
			DrawShadow(drawRegion, -depth, ccode);
		else
			DrawShadow(drawRegion, depressed ? -1 : depth, ccode);
	}

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

	// Add a margin between the border/shadow and the focus rect/data.
	if (defaultButton || Focus() || Bordered())
	{
		drawRegion--;
		focusRegion--;
	}

	// Draw the focus rectangle.
	if (focus)
		DrawFocus(focusRegion, ccode);

	// Set the clipping region.
	display->SetClipRegion(drawRegion);

	if (ccode == S_REDISPLAY || ccode == S_REDISPLAY_DATA || ccode == S_REDISPLAY_REGION)
	{
		// Create a depression sensation by moving drawRegion down and right.
		if (depressed && ButtonType() != ZAF_FLAT_BUTTON)
		{
			drawRegion.left++;
			drawRegion.top++;
			drawRegion.right++;
			drawRegion.bottom++;
		}

		// Set the text palette.
		ZafPaletteStruct textPalette = LogicalPalette(ZAF_PM_TEXT, state);
		display->SetPalette(textPalette);

		// Compute regions.
		ZafRegionStruct textRegion;
		if (stringData)
			textRegion = display->TextSize(*stringData);
		else
		{
			textRegion.coordinateType = ZAF_PIXEL;
			textRegion.left = textRegion.top = 1;
			textRegion.right = textRegion.bottom = 0;
		}
		ZafRegionStruct imageRegion;
		imageRegion.coordinateType = ZAF_PIXEL;
		imageRegion.left = imageRegion.top = 1;
		if (bitmapData)
		{
			imageRegion.right = bitmapData->width;
			imageRegion.bottom = bitmapData->height;
		}
		else
			imageRegion.right = imageRegion.bottom = 0;

		if (ButtonType() == ZAF_FLAT_BUTTON && hzJustify == ZAF_HZ_LEFT)
			drawRegion.left += 2 * ZAF_BORDER_SIZE;

		ComputeDrawRegions(drawRegion, imageRegion, textRegion, 4);

		// Draw the bitmap.
		if (bitmapData)
			display->Bitmap(imageRegion.left, imageRegion.top, *bitmapData);

		// Draw the text.
		if (stringData)
		{
/* START BLOCK COMMENT
**				if (Disabled())
**				{
**					display->SetPalette(textPalette);
**	
**					// If disabled, chisel color is in palette background.
**					display->SetForeground(textPalette.colorBackground);
**					display->Text(textRegion.left + 1, textRegion.top + 1, textRegion.right + 1,
**						textRegion.bottom + 1, *stringData, -1, HzJustify(), ZAF_VT_CENTER, hotKeyIndex, false);
**				}
END BLOCK COMMENT */
			display->SetPalette(textPalette);
			display->Text(textRegion, *stringData, -1, ZAF_HZ_CENTER, ZAF_VT_CENTER, hotKeyIndex, false);
		}
	}

	EndDraw();
	return (ccode);
}

ZafEventType ZafButton::DrawBorder(ZafRegionStruct &region, ZafEventType ccode)
{
	if (ParentDrawBorder())
	{
		ZafRegionStruct borderRegion = parent->ConvertToDrawRegion(this);
		return parent->DrawBorder(borderRegion, ccode);
	}

	if (ccode == S_REDISPLAY || ccode == S_REDISPLAY_REGION)
	{
		// Draw a single pixel border.
		display->SetPalette(LogicalPalette(ZAF_PM_OUTLINE, PaletteState()));
		display->Rectangle(region, 1, false);
	}

	// Update the draw region.
	region--;

	return (ccode);
}

ZafEventType ZafButton::DrawFocus(ZafRegionStruct &region,
	ZafEventType ccode)
{
	if (ParentDrawFocus())
	{
		ZafRegionStruct focusRegion = ConvertToDrawRegion(this, &zafRegion);
		ccode = parent->DrawFocus(focusRegion, ccode);
	}
	else
	{
		display->SetPalette(*((ZafScreenDisplay *)display)->xorPalette);
		display->SetMode(ZAF_MODE_XOR);
		display->Rectangle(region, -1);
		display->SetMode(ZAF_MODE_COPY);
	}

	return (ccode);
}

ZafEventType ZafButton::DrawShadow(ZafRegionStruct &region, int depth,
	ZafEventType ccode)
{
	ZafPaletteStruct lightShadow = LogicalPalette(ZAF_PM_LIGHT_SHADOW, 0);
	ZafPaletteStruct darkShadow = LogicalPalette(ZAF_PM_DARK_SHADOW, 0);
	ZafPaletteStruct whiteShadow = lightShadow;
	ZafPaletteStruct blackShadow = darkShadow;

	// 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;
	blackShadow.colorForeground = blackShadow.colorBackground;

	if (depth == -1)
	{
		// Draw a dark rectangle discernable on a gray background.
		display->SetPalette(darkShadow);
		display->Rectangle(region);
		--region;
		return (ccode);
	}

	if (depth > 0)
	{
		// Draw the shadow pattern.
		display->SetPalette(whiteShadow);
		display->Line(region.left, region.top, region.right - 1, region.top);
		display->Line(region.left, region.top, region.left, region.bottom - 1);

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

		if (depth > 1)
		{
			display->SetPalette(lightShadow);
			display->Line(region.left + 1, region.top + 1, region.right - 1, region.top + 1);
			display->Line(region.left + 1, region.top + 1, region.left + 1, region.bottom - 1);

			display->SetPalette(darkShadow);
			display->Line(region.left + 1, region.bottom - 1, region.right - 1, region.bottom - 1);
			display->Line(region.right - 1, region.top + 1, region.right - 1, region.bottom - 1);
		}
	}
	else if (depth < 0) // Selected toggle button.
	{
		// Draw the shadow pattern.
		display->SetPalette(blackShadow);
		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);

		if (depth < -1)
		{
			display->SetPalette(darkShadow);
			display->Line(region.left + 1, region.top + 1, region.right - 1, region.top + 1);
			display->Line(region.left + 1, region.top + 1, region.left + 1, region.bottom - 1);

			display->SetPalette(lightShadow);
			display->Line(region.left + 1, region.bottom - 1, region.right - 1, region.bottom - 1);
			display->Line(region.right - 1, region.top + 1, region.right - 1, region.bottom - 1);
		}
	}

	region -= ZafAbs(depth);

	return (ccode);
}
#endif

ZafEventType ZafButton::Event(const ZafEventStruct &event)
{
	static ZafWindowObject *lastSelected = ZAF_NULLP(ZafWindowObject);

	ZafEventType ccode = LogicalEvent(event);

	if ((editMode || modifyMode) && event.InputType() == E_MOUSE && ccode != L_VIEW)
		return (Modify(event));

	// Check for zinc events.
	switch (ccode)
	{
	// ----- Create messages -----
	case S_INITIALIZE:
		ccode = ZafWindowObject::Event(event);
		if (buttonType == ZAF_RADIO_BUTTON)
		{
			SetBitmapData(Selected() ? radioSelectedBitmap : radioBitmap);
			depth = 0;
		}
		else if (buttonType == ZAF_CHECK_BOX)
		{
			SetBitmapData(Selected() ? checkSelectedBitmap : checkBitmap);
			depth = 0;
		}
		break;

	case S_COMPUTE_SIZE:
		ZafWindowObject::Event(event);
#if defined(ZAF_TEXT_MODE)
		zafRegion.top = zafRegion.bottom;
#else
		// Set initial height.
		if (autoSize)
		{
			// Get the text size.
			display->SetFont(LogicalPalette(ZAF_PM_TEXT, 0).font);
			ZafRegionStruct textRegion;
			if (stringData)
				textRegion = display->TextSize(*stringData);
			else
			{
				textRegion.coordinateType = zafRegion.coordinateType;
				textRegion.left = textRegion.top = 1;
				textRegion.right = textRegion.bottom = 0;
			}

			ZafRegionStruct imageRegion;
			imageRegion.coordinateType = zafRegion.coordinateType;
			imageRegion.left = imageRegion.top = 1;
			if (ButtonType() == ZAF_CHECK_BOX || ButtonType() == ZAF_RADIO_BUTTON)
			{
				imageRegion.right = checkBitmap->width;
				imageRegion.bottom = checkBitmap->height;
			}
			else if (bitmapData)
			{
				imageRegion.right = bitmapData->width;
				imageRegion.bottom = bitmapData->height;
			}
			else
				imageRegion.right = imageRegion.bottom = 0;

			ZafRegionStruct drawRegion;
			drawRegion.coordinateType = zafRegion.coordinateType;
			drawRegion.left = drawRegion.top = 1;
			drawRegion.right = drawRegion.bottom = 0;
			ComputeDrawRegions(drawRegion, imageRegion, textRegion, 4);
			int height = drawRegion.Height();

			if (ButtonType() == ZAF_CHECK_BOX || ButtonType() == ZAF_RADIO_BUTTON)
			{
				int centerY = zafRegion.top + zafRegion.Height() / 2;
				zafRegion.top = centerY - height / 2;
				zafRegion.bottom = zafRegion.top + height - 1;
			}
			else
			{
				if (!bitmapData)
					height = 23;
				else
				{
					if (ButtonType() == ZAF_NATIVE_BUTTON || ButtonType() == ZAF_3D_BUTTON)
						height += 2 * depth;
					height += 6;
				}

				zafRegion.top = zafRegion.bottom - height + 1;
			}
		}
#endif
		break;

	case S_HOT_KEY:
		if (!Disabled() && hotKeyChar && event.key.value == hotKeyChar)
			Event(L_SELECT);
		else
			ccode = S_UNKNOWN;
		break;

	// ----- Actions -----
	case L_DOUBLE_CLICK:
		// Make sure the button double-clicks.
		if (selectOnDoubleClick)
		{
			(this->*memberUserFunction)(event, ccode);
			if (!autoRepeatSelection)
				break;
		}
		// else continue.
	case L_BEGIN_SELECT:
		if (editMode)
		{
			ZafWindowObject::Event(event);
			break;
		}

		// Break if the button is disabled.
		if (Disabled())
			break;

		if (Draggable())
			ZafWindowObject::Event(event);

		lastSelected = this;
		SetDepressed(true);
		if (autoRepeatSelection)
		{
			ZafTimer *repeatTimer = new ZafTimer(D_ON, InitialDelay());
			repeatTimer->Add(this, N_INITIAL_DELAY);
			repeatTimer->SetStringID(ZAF_ITEXT("ZafButtonRepeat"));
			eventManager->Add(repeatTimer);
			windowManager->CaptureMouse(this);
		}
		else if (selectOnDownClick)
			Event(L_SELECT);
		else if (depth &&
			(buttonType == ZAF_3D_BUTTON || buttonType == ZAF_NATIVE_BUTTON ||
			buttonType == ZAF_TOOLBAR_BUTTON) &&
			!parent->IsA(ID_ZAF_SPIN_CONTROL))
			windowManager->CaptureMouse(this);
		break;

	case N_INITIAL_DELAY:
		{
			if (depressed)
				(this->*memberUserFunction)(event, L_SELECT);
			ZafTimer *repeatTimer = DynamicPtrCast(eventManager->GetObject(ZAF_ITEXT("ZafButtonRepeat")),
				ZafTimer);
			if (repeatTimer)
			{
				repeatTimer->Subtract(this);
				repeatTimer->Add(this, N_REPEAT_DELAY);
//				repeatTimer->SetNotifyMessage(N_REPEAT_DELAY);
				repeatTimer->SetInterval(RepeatDelay());
			}
		}
		break;

	case N_REPEAT_DELAY:
		{
			if (depressed)
				(this->*memberUserFunction)(event, L_SELECT);
		}
		break;

	case E_MOUSE:
	case L_CONTINUE_SELECT:
//	case S_CONTINUE_COPY_DRAG:
		{
			if (ccode == E_MOUSE && !(event.rawCode & M_LEFT))
				break;

			// All mouse messages initially go to the button being dragged before
			// being converted and dispatched to the item being dragged over.
			if (Draggable())
				ZafWindowObject::Event(event);

/* START BLOCK COMMENT
**				if (windowManager->dragObject)
**				{
**					ZafWindowObject::Event(event);
**					break;
**				}
END BLOCK COMMENT */

			if (lastSelected != this)
				break;

			// Check if the mouse is overlapping the button.  It is possible
			// that it won't if the event comes from a local event loop. For
			// example, L_BEGIN_SELECT in the maximize button loops until the 
			// user releases the mouse button.
			// Get mouse coordinates relative to parent, since zafRegion is
			// relative to parent.
			ZafPositionStruct mousePosition = event.position;
			mousePosition.line += zafRegion.top;
			mousePosition.column += zafRegion.left;

			if (!zafRegion.Overlap(mousePosition))
			{
				if (depressed)
					SetDepressed(false);
			}
			else
			{
				if (!depressed)
					SetDepressed(true);
			}
		}
		break;

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

			if (zafWindowManager->dragObject)
				ZafWindowObject::Event(event);

			if (windowManager->MouseEventRoute() == this)
				windowManager->CaptureMouse(ZAF_NULLP(ZafWindowObject));

			if (autoRepeatSelection)
			{
				ZafDevice *repeatTimer = eventManager->GetObject(ZAF_ITEXT("ZafButtonRepeat"));
				if (repeatTimer)
				{
					eventManager->Subtract(repeatTimer);
					delete repeatTimer;
				}
			}

			// Check if the mouse is overlapping the button. It is possible
			// that it won't if the event comes from a local event loop. For
			// example, L_BEGIN_SELECT in the maximize button loops until the
			// user releases the mouse button.
			// Get mouse coordinates relative to parent, since zafRegion is
			// relative to parent.
			ZafPositionStruct mousePosition = event.position;
			mousePosition.line += zafRegion.top;
			mousePosition.column += zafRegion.left;

			if (lastSelected != this || !zafRegion.Overlap(mousePosition))
				break;

			SetDepressed(false);

			if (selectOnDownClick)
				break;

			if (!Disabled())
			{
				if (parent && allowToggling)
				{
					if (DynamicPtrCast(parent, ZafWindow)->SelectionType() != ZAF_SINGLE_SELECTION)
						SetSelected(!Selected());
					else
						SetSelected(true);
				}
			}

			(this->*memberUserFunction)(L_END_SELECT, L_SELECT);
			lastSelected = this;
		}
		break;

	case L_SELECT:
		// The ENTER key should select all types of buttons but the
		// default button should get it first, if it exists.
		if (!Disabled())
		{
			ZafButton *defaultButton = DynamicPtrCast(RootObject(), ZafWindow)->DefaultButton();
			if (!defaultButton || buttonType != ZAF_CHECK_BOX && buttonType != ZAF_RADIO_BUTTON ||
			 event.key.value == ' ')
			{
				if (parent && allowToggling)
				{
					if (DynamicPtrCast(parent, ZafWindow)->SelectionType() != ZAF_SINGLE_SELECTION)
						SetSelected(!Selected());
					else
						SetSelected(true);
				}
				(this->*memberUserFunction)(event, L_SELECT);
			}
			else if (defaultButton)
				ccode = 0;
		}
		break;

	case S_CURRENT:
	case S_NON_CURRENT:
		ZafWindowObject::Event(event);
		Event(S_REDISPLAY);
		break;

	case S_COPY_DATA:
		{
			ZafWindowObject *object = event.windowObject;
			ZafButton *button = DynamicPtrCast(object, ZafButton);
			if (!button)
				break;

			bitmapData->SetBitmap(*button->BitmapData());
		}
		break;

	case S_SET_DATA:
		{
			ZafWindowObject *object = event.windowObject;
			if (object)
			{
				ZafButton *button = DynamicPtrCast(object, ZafButton);
				if (!button)
					break;

				SetBitmapData(button->BitmapData());
			}
			else
				SetBitmapData(new ZafBitmapData(*bitmapData));
		}
		break;

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

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

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

bool ZafButton::SetDepressed(bool tDepressed)
{
	if (!depth)
		return (tDepressed);

	bool changedDepressed = false;
	if (depressed != tDepressed)
		changedDepressed = true;
	depressed = tDepressed;

	if (changedDepressed)
		Redisplay();
	return (depressed);
}

bool ZafButton::SetDisabled(bool setDisabled)
{
	return (ZafWindowObject::SetDisabled(setDisabled));
}

bool ZafButton::SetNoncurrent(bool setNoncurrent)
{
	// Defer to the base class.
	return (ZafWindowObject::SetNoncurrent(setNoncurrent));
}

bool ZafButton::SetSelected(bool tSelected)
{
	if (selected != tSelected)
	{
		ZafWindowObject::SetSelected(tSelected);

		if (buttonType == ZAF_RADIO_BUTTON)
			SetBitmapData(selected ? radioSelectedBitmap : radioBitmap);
		else if (buttonType == ZAF_CHECK_BOX)
			SetBitmapData(selected ? checkSelectedBitmap : checkBitmap);

		if (screenID)
			Redisplay();
	}

	return (selected);
}

bool ZafButton::SetVisible(bool visible)
{
	return (ZafWindowObject::SetVisible(visible));
}

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

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

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

void ZafButton::OSRegisterObject(void)
{
	ZafWindowObject::OSRegisterObject();

/* START BLOCK COMMENT
**		// Determine the user function.
**		if (SendMessageWhenSelected())
**			memberUserFunction = (MemberUserFunction)&ZafButton::SendMessage;
**		else if (memberUserFunction == (MemberUserFunction)&ZafButton::SendMessage)
**			memberUserFunction = &ZafWindowObject::DefaultUserFunction;
END BLOCK COMMENT */
}

ZafError ZafButton::OSSetImage(void)
{
	if (screenID)
	{
		Event(ZafEventStruct(S_COMPUTE_SIZE));
		OSSize();
		Redisplay();
	}
	return (ZAF_ERROR_NONE);
}

ZafError ZafButton::OSSetText(void)
{
	if (screenID)
		Event(S_REDISPLAY);
	else
	{
		ZafMessageData *messageData = DynamicPtrCast(stringData, ZafMessageData);
		if (messageData)
		{
			SetHotKey(messageData->HotKeyChar(), messageData->HotKeyIndex());
		}
	}
	return (ZAF_ERROR_NONE);
}

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

ZafError ZafButton::OSUpdatePalettes(ZafPaletteType zafTypes, ZafPaletteType osTypes)
{
	// Defer to the base class.
	return (ZafWindowObject::OSUpdatePalettes(zafTypes, osTypes));
}
