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

#include <z_icon1.hpp>
#include <z_string.hpp>
#include <z_app.hpp>
#define ZAF_ICON_INFO
#include "img_def.cpp"
#include "gbl_def.cpp"
#if defined(ZAF_MSWINDOWS)
#	include <w_app.hpp>
#elif defined(ZAF_MACINTOSH)
#	include <Icons.h>
#endif

ZafIcon *ZafWindow::MinimizeIcon(void) const
{
	for (ZafWindowObject *object = SupportFirst(); object; object = object->Next())
		if (object->NumberID() == ZAF_NUMID_MIN_ICON)
			return (DynamicPtrCast(object, ZafIcon));
	return (ZAF_NULLP(ZafIcon));
}

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

static ZafStringIDChar ZAF_FARDATA _stringID[] = ZAF_ITEXT("ZAF_NUMID_MIN_ICON");

ZafIcon::ZafIcon(int left, int top, const ZafIChar *text,
	ZafIconData *zIconData, ZafIconType tIconType) :
	ZafButton(left, top, 0, 0, text, ZAF_NULLP(ZafBitmapData), ZAF_FLAT_BUTTON),
	iconType(ZAF_NATIVE_ICON), iconData(ZAF_NULLP(ZafIconData))
#if defined(ZAF_INDEPENDENT)
	, initialized(false)
#endif
{
	// Initialize the environment-specific information.
#if !defined(ZAF_MOTIF)
	SetDepth(0);
#endif

	// Initialize the icon information.
	SetButtonType(ZAF_FLAT_BUTTON);
	SetSelectOnDoubleClick(true);
	SetIconType(tIconType);

	// Check the image information.
	ImageAllocate();

	// Set the icon only if it was not previously set.
	if (!iconData && zIconData)
		SetIconData(zIconData);
}

ZafIcon::ZafIcon(int left, int top, ZafStringData *zStringData,
	ZafIconData *zIconData, ZafIconType tIconType) :
	ZafButton(left, top, 0, 0, zStringData, ZAF_NULLP(ZafBitmapData), ZAF_FLAT_BUTTON),
	iconType(ZAF_NATIVE_ICON), iconData(ZAF_NULLP(ZafIconData))
#if defined(ZAF_INDEPENDENT)
	, initialized(false)
#endif
{
	// Initialize the environment-specific information.
#if !defined(ZAF_MOTIF)
	SetDepth(0);
#endif

	// Initialize the icon information.
	SetButtonType(ZAF_FLAT_BUTTON);
	SetSelectOnDoubleClick(true);
	SetIconType(tIconType);

	// Check the image information.
	ImageAllocate();

	// Set the icon only if it was not previously set.
	if (!iconData && zIconData)
		SetIconData(zIconData);
}

ZafIcon::ZafIcon(const ZafIcon &copy) :
	ZafButton(copy),
	iconType(copy.iconType), iconData(ZAF_NULLP(ZafIconData))
#if defined(ZAF_INDEPENDENT)
	, initialized(false)
#endif
{
	// Check the image information.
	ImageAllocate();

	// Set the icon information.
	if (iconType == ZAF_MINIMIZE_ICON)
	{
		SetNumberID(ZAF_NUMID_MIN_ICON);
		SetStringID(_stringID);
		SetSupportObject(true);
	}

	// Initialize the icon information.
	if (!copy.iconData)
		;
	else if (copy.iconData->Destroyable())
		SetIconData(new ZafIconData(*copy.iconData));
	else
		SetIconData(copy.iconData);
}

ZafIcon::~ZafIcon(void)
{
	// Remove the data notification.
	if (iconData)
		iconData->SubtractNotification(this, (ZafUpdateFunction)Update);

	// Check the image information.
	ImageFree();

	// Restore the icon information.
	if (iconData && iconData->Destroyable() && iconData->NotifyCount() == 0)
		delete iconData;
}

void ZafIcon::ClearImage(void)
{
	// Make sure the request is valid.
	if (!iconData)
		return;

	// Clear the image.
	SetIconData(ZAF_NULLP(ZafIconData));
}

ZafEventType ZafIcon::DragDropEvent(const ZafEventStruct &event)
{
	// Switch on the event type.
	ZafEventType ccode = event.type;
	switch (ccode)
	{
	case S_DROP_DEFAULT:
	case S_DROP_MOVE:
		// ZafIcon treats S_DROP_MOVE as S_DROP_COPY.

	case S_DROP_COPY:
		if (!Disabled() && AcceptDrop() && windowManager->dragObject != this)
		{
			ZafIcon *dragIcon = DynamicPtrCast(windowManager->dragObject, ZafIcon);
			if (dragIcon)
			{
				if (dragIcon->iconData != iconData)
					SetIconData(dragIcon->iconData);
				if (dragIcon->Text() != Text())
					SetText(dragIcon->Text());
			}
			else
				ccode = ZafWindowObject::DragDropEvent(event);
		}
		else
			ccode = S_ERROR;
		break;

	default:
		ccode = ZafWindowObject::DragDropEvent(event);
		break;
	}

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

ZafWindowObject *ZafIcon::Duplicate(void)
{
	return (new ZafIcon(*this));
}

void ZafIcon::ImageAllocate(void)
{
#if !defined(ZAF_TEXT_MODE)
	// Check for an allocated table.
	if (imageTable)
		return;

	// Define icon resources.
#if defined(__hpux)  // HP compilers require this to be a static structure.
	static struct SYS_ICON 
#else
	struct SYS_ICON 
#endif
	{
		ZafIconImage imageID;
		ZafStringID name;
		ZafIconStruct *image;
	} _icon[] =
	{
		{ ZAF_APPLICATION_ICON, applicationName, &_application_ZafIcon },
		{ ZAF_ASTERISK_ICON, asteriskName, &_asterisk_ZafIcon },
		{ ZAF_EXCLAMATION_ICON, exclamationName, &_exclamation_ZafIcon },
		{ ZAF_HAND_ICON, handName, &_hand_ZafIcon },
		{ ZAF_QUESTION_ICON, questionName, &_question_ZafIcon },
		{ 0, 0, 0 }
	};

	// Initialize the icon images.
	ZafI18nData::AddStaticModule(ImageFree);
	imageTable = new ZafIconData *[sizeof(_icon) / sizeof(SYS_ICON)];
	int i;
	for (i = 0; _icon[i].name; i++)
	{
		imageTable[i] = new ZafIconData(*_icon[i].image);
		imageTable[i]->SetStringID(_icon[i].name);
		imageTable[i]->SetNumberID(_icon[i].imageID);
		imageTable[i]->staticHandle = true;
		imageTable[i]->SetDestroyable(false);
	}
	imageTable[i] = ZAF_NULLP(ZafIconData);

	// Environment specific initialization.
#	if defined(ZAF_WIN32)
	imageTable[ZAF_APPLICATION_ICON]->handle = LoadIconA(NULL, (char *)IDI_APPLICATION);
	imageTable[ZAF_ASTERISK_ICON]->handle = LoadIconA(NULL, (char *)IDI_ASTERISK);
	imageTable[ZAF_EXCLAMATION_ICON]->handle = LoadIconA(NULL, (char *)IDI_EXCLAMATION);
	imageTable[ZAF_HAND_ICON]->handle = LoadIconA(NULL, (char *)IDI_HAND);
	imageTable[ZAF_QUESTION_ICON]->handle = LoadIconA(NULL, (char *)IDI_QUESTION);
#	elif defined(ZAF_MSWINDOWS)
	imageTable[ZAF_APPLICATION_ICON]->handle = LoadIcon(NULL, IDI_APPLICATION);
	imageTable[ZAF_ASTERISK_ICON]->handle = LoadIcon(NULL, IDI_ASTERISK);
	imageTable[ZAF_EXCLAMATION_ICON]->handle = LoadIcon(NULL, IDI_EXCLAMATION);
	imageTable[ZAF_HAND_ICON]->handle = LoadIcon(NULL, IDI_HAND);
	imageTable[ZAF_QUESTION_ICON]->handle = LoadIcon(NULL, IDI_QUESTION);
#	elif defined(ZAF_MACINTOSH)
	imageTable[ZAF_ASTERISK_ICON]->handle = GetIcon(kNoteIcon);
	imageTable[ZAF_EXCLAMATION_ICON]->handle = GetIcon(kCautionIcon);
	imageTable[ZAF_HAND_ICON]->handle = GetIcon(kStopIcon);
#	endif
#endif
}

void ZafIcon::ImageFree(bool globalRequest)
{
#if !defined(ZAF_TEXT_MODE)
	// Destroy the static images.
	if (globalRequest && imageTable)
	{
		for (int i = 0; imageTable[i]; i++)
		{
			imageTable[i]->staticHandle = false;
			delete imageTable[i];
		}
		delete []imageTable;
		imageTable = ZAF_NULLP(ZafIconData *);
	}
#endif
}

bool ZafIcon::IsA(ZafClassID compareID) const
{
	return ((compareID == classID) ? true : ZafButton::IsA(compareID));
}

bool ZafIcon::IsA(ZafClassName compareName) const
{
	return (!strcmp(compareName, className) ? true : ZafButton::IsA(compareName));
}

const ZafPaletteStruct *ZafIcon::MapClassPalette(ZafPaletteType type, ZafPaletteState state)
{
	const ZafPaletteStruct *palette = MapPalette(defaultPaletteMap, type, state);
	return (palette ? palette : ZafButton::MapClassPalette(type, state));
}

bool ZafIcon::SetAllowDefault(bool )
{
	// allowDefault is false for this class.
	allowDefault = false;
	return (allowDefault);
}

bool ZafIcon::SetAllowToggling(bool )
{
	// allowToggling is false for this class.
	allowToggling = false;
	return (allowToggling);
}

bool ZafIcon::SetAutoRepeatSelection(bool )
{
	// autoRepeatSelection is false for this class.
	autoRepeatSelection = false;
	return (autoRepeatSelection);
}

ZafError ZafIcon::SetBitmapData(ZafBitmapData *)
{
	// bitmapData is null for this class.
	bitmapData = ZAF_NULLP(ZafBitmapData);
	return (ZAF_ERROR_INVALID);
}

ZafButtonType ZafIcon::SetButtonType(ZafButtonType )
{
	// buttonType is ZAF_FLAT_BUTTON for this class.
	buttonType = ZAF_FLAT_BUTTON;
	return (buttonType);
}

int ZafIcon::SetDepth(int )
{
#if defined(ZAF_MOTIF)
	// depth is 2 for this class.
	depth = 2;
#else
	// depth is 0 for this class.
	depth = 0;
#endif
	return (depth);
}

ZafIChar ZafIcon::SetHotKey(ZafIChar , int )
{
	// hotKeyChar and hotKeyIndex are unchanged for this class.
	hotKeyChar = 0;
	hotKeyIndex = -1;
	return (hotKeyChar);
}

ZafError ZafIcon::SetIconData(ZafIconData *zIconData)
{
	// Remove the data notification.
	if (iconData)
		iconData->SubtractNotification(this, (ZafUpdateFunction)Update);

	// Reset the icon data.
	if (iconData && iconData != zIconData &&
		iconData->Destroyable() && iconData->NotifyCount() == 0)
		delete iconData;
	iconData = zIconData;

	// Add the data notification.
	if (iconData)
		iconData->AddNotification(this, (ZafUpdateFunction)Update);
	return (OSSetImage());
}

ZafIconData *ZafIcon::SetIconImage(ZafIconImage iconImage)
{
	// Try to find a matching image.
	for (int i = 0; imageTable[i]; i++)
		if (imageTable[i]->NumberID() == iconImage)
		{
			SetIconData(imageTable[i]);
			break;
		}
	return (iconData);
}

ZafIconType ZafIcon::SetIconType(ZafIconType setIconType)
{
	// Make sure the attribute has changed.
	if (iconType != setIconType && !screenID)
	{
		iconType = setIconType;

		// Set the icon information.
		if (iconType == ZAF_MINIMIZE_ICON)
		{
			SetNumberID(ZAF_NUMID_MIN_ICON);
			SetStringID(_stringID);
			SetSupportObject(true);
		}
	}

	// Return the current attribute.
	return (iconType);
}

ZafRegionType ZafIcon::SetRegionType(ZafRegionType )
{
	// regionType is ZAF_INSIDE_REGION for this class.
	regionType = ZAF_INSIDE_REGION;
	return (regionType);
}

bool ZafIcon::SetSupportObject(bool setSupportObject)
{
	// Make sure the attribute has changed.
	if (!parent && supportObject != setSupportObject)
		supportObject = setSupportObject;

	// Return the current attribute.
	return (supportObject);
}

ZafError ZafIcon::Update(ZafIcon *icon, ZafUpdateType type)
{
	ZafError retVal = ZAF_ERROR_INVALID;
	if (type & ZAF_UPDATE_OBJECT)
		retVal = icon->OSSetImage();
	if (type & ZAF_UPDATE_DATA)
		retVal = ZAF_ERROR_NONE;
	
	return (retVal);
}

// ----- Persistent functions -----------------------------------------------
#if defined(USE_ZAF_PERSISTENCE)
ZafIcon::ZafIcon(const ZafIChar *name, ZafObjectPersistence &persist) :
	ZafButton(name, persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY)),
	iconData(ZAF_NULLP(ZafIconData))
#if defined(ZAF_INDEPENDENT)
	, initialized(false)
#endif
{
	// Check the image information.
	ImageAllocate();

	// Read the data.
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafIcon::ReadData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());

	// Set the icon information.
	if (iconType == ZAF_MINIMIZE_ICON)
	{
		SetNumberID(ZAF_NUMID_MIN_ICON);
		SetStringID(_stringID);
		SetSupportObject(true);
	}
}

ZafElement *ZafIcon::Read(const ZafIChar *name, ZafObjectPersistence &persist)
{
	return (new ZafIcon(name, persist));
}

void ZafIcon::ReadData(ZafObjectPersistence &persist)
{
	// Read the data.
	ZafIChar iconName[ZAF_MAXNAMELEN];
	ZafUInt16 flag1;
	ZafFile *file = persist.CurrentFile();
	*file >> flag1 >> iconName;
	iconType = (ZafIconType)(flag1 & 0x000F);

	// Read the icon data.
	if (*iconName)
	{
		// Check the icon table.
		for (int i = 0; imageTable[i]; i++)
			if (!strcmp(imageTable[i]->StringID(), iconName))
			{
				SetIconData(imageTable[i]);
				return;
			}

		// Read the image from disk.
		SetIconData(new ZafIconData(iconName, persist));
	}
}

void ZafIcon::Write(ZafObjectPersistence &persist)
{
	// Write the object.
	ZafButton::Write(persist.PushLevel(className, classID, ZAF_PERSIST_DIRECTORY));
	if (persist.Error() == ZAF_ERROR_NONE)
		ZafIcon::WriteData(persist);
	persist.PopLevel();
	if (persist.Error() != ZAF_ERROR_NONE)
		SetError(persist.Error());
}

void ZafIcon::WriteData(ZafObjectPersistence &persist)
{
	// Write the icon information.
	ZafUInt16 flag1 = 0;
	flag1 |= (ZafUInt16)(iconType & 0x000F);
	const ZafIChar *iconName = iconData ? iconData->StringID() : ZAF_NULLP(ZafIChar);
	ZafFile *file = persist.CurrentFile();
	*file << flag1 << iconName;

	// Write the icon data.
	if (iconData)
		iconData->Write(persist);
}
#endif
