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

//	Example program showing a multilingual application using
//	ZafLanguageManager, ZafLanguageData and ZafMessageData.
//	This generic application's entire UI (in language.znc)
//	can be changed without any modifications to this code.

//  Note: This program requires ZAF 5.11 *plus* updated
//  versions of z_win.hpp, z_winobj.cpp, and z_lang.cpp.
//  These updates will be included in future ZAF revisions.


#include "langwin.hpp"

LanguageWindow::LanguageWindow(const ZafIChar *name, ZafObjectPersistence &persist) :
	ZafWindow(name, persist)
{
  // The LanguageWindow constructor does four important things:
	//
	// 1. Accesses language.znc as a ZafDataPersistence to be used when
	//    loading messages.
	//
	// 2. Loads the ZafLanguageData "LanguageStrings" containing all the
	//    messages used by the application.  The default system language
	//    is accessed first.
	//
	// 3. Walks the list of messages contained in the ZafLanguageData and
	//    attempts to match their stringIDs with the stringIDs of the
	//    LanguageWindow and its children.
	//
	// 4. If a match is found, convert the ZafMessageStruct to a
	//    ZafMessageData (a derived ZafStringData) and replace the
	//    ZafWindowObject's default ZafStringData.  This is the real
	//    trick to creating an automatic multilingual application.
	//    Once the ZafMessageDatas are associated with the
	//    ZafWindowObjects, they may be swapped for other versions
	//    (translations) without any programmer code.  ZafNotification
	//    functionality inherited by ZafMessageData will take care of
	//    updating our user interface.

	// 1.
	// zafLanguageManager uses zafDataPersistence to load language data.
	// Since our language data is in the same file as UI objects
	// (language.znc) we need to share it.

	if (zafDataPersistence && zafDataPersistence != zafObjectPersistence)
	{
		// Subtract all file systems (like i18n.znc) from zafDataPersistence 
		// and add them to zafObjectPersistence.
		ZafFileSystem *fileSystem = zafDataPersistence->FirstFileSystem();
		while (fileSystem)
		{
			zafDataPersistence->SubtractFileSystem(fileSystem);
			zafObjectPersistence->AddFileSystem(fileSystem);
			fileSystem = zafDataPersistence->FirstFileSystem();
		}

		delete zafDataPersistence;
	}

	// Use zafObjectPersistence as zafDataPersistence as well, so we can
	// share language.znc.
	zafDataPersistence = zafObjectPersistence;

	// 2.
	// Allocate a ZafLanguageData that will be managed by the 
	// ZafLanguageManager.  ZafLanguageManager will update this language
	// (when we change translations) and delete it automatically when the
	// application terminates.

	ZafLanguageData *languageData = zafLanguageManager->Allocate(ZAF_ITEXT("LanguageStrings"));

	if (!languageData)
	{
		languageData = new ZafLanguageData(ZAF_ITEXT("LanguageStrings"), *zafDataPersistence,
			ZAF_ITEXT("en"));
		zafLanguageManager->Add(languageData);
	}

	// 3.
	// Walk the messages in the ZafLanguageData list and find matching
	// WindowObjects on the window (using the same stringID).  Matching
	// stringIDs is our application's technique for loosely binding
	// ZafWindowObjects to related messages in ZafLanguageData objects.

	ZafMessageStruct *message = *languageData;  // (Operator overload.)
	while (message->stringID)
	{
		ZafWindowObject *object = GetObject(message->stringID);
		if (object)
			// 4.
			// Convert the message struct to a ZafMessageData
			// and replace the ZafWindowObject's default
			// ZafStringData with the managed version.

			object->SetStringData(languageData->GetMessageData(message->stringID));
		message++;
	}
}


LanguageWindow::~LanguageWindow(void)
{
}


ZafEventType LanguageWindow::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;
	
	switch (ccode)
	{
	case S_DEINITIALIZE:
		ccode = ZafWindow::Event(event);
		// We set zafDataPersistence == zafObjectPersistence above
		zafDataPersistence = ZAF_NULLP(ZafDataPersistence);
		break;

	case CHANGE_LANGUAGE:
		// (value 10000) sent by language menu items.  event.text
		// contains the identification of the language selected.
		//
		// ZAF Magic: SetLanguage() causes the language manager to
		// reload messages for managed ZafLanguageDatas.  Associated
		// ZafMessageDatas therefore receive new data.  These message
		// datas are tied to ZafWindowObjects by data notification and
		// automatically notify the WindowObjects to redisplay their
		// data.  This updates the entire UI with one simple call.

		zafLanguageManager->SetLanguage(event.text);

		// We're responsible to clean up event.text in user events.
		delete event.text;
		break;

	default:
		ccode = ZafWindow::Event(event);
	}

	return (ccode);
}
