// COPYRIGHT (C) 1990-1999.  All Rights Reserved. - BITMAP5.CPP
// Zinc Software Incorporated.  Pleasant Grove, Utah  USA
// May be freely copied, used and distributed.

#include <zaf.hpp>
#include <z_utils.hpp>
#include <z_prst.hpp>
#include "bitmap2.hpp"
#include "bitmap4.hpp"
#include "bitmap5.hpp"

// Callback for the slider.
ZafEventType ChangeInterval(ZafWindowObject *, ZafEventStruct &, ZafEventType ccode)
{
	if (ccode == L_SELECT)
		zafEventManager->Put(U_ADJUST_TIMER);

	return (0);
}

// Constructor loads the window from the persistence file.
ControlWindow::ControlWindow(ZafIChar *name, ZafObjectPersistence &persist) :
	ZafWindow(name, persist), bitmapCounter(0)
{
	// Initialize my protected members.
	slider = DynamicPtrCast(GetObject(ZAF_ITEXT("SLIDER")), ZafScrollBar);
	slider->SetUserFunction(ChangeInterval);
	bitmapCombo = DynamicPtrCast(GetObject(ZAF_ITEXT("ACTIVE_BITMAP")), ZafComboBox);

	currentInterval = DynamicPtrCast(GetObject(ZAF_ITEXT("CURRENT_INTERVAL")), ZafInteger);
	zafWindowManager->Center(this);

	if (zafDataPersistence != zafObjectPersistence)
		delete zafDataPersistence;
	zafDataPersistence = zafObjectPersistence;
}

// Destructor cleans up any of its own data.
ControlWindow::~ControlWindow()
{
}

BitmapWindow::BitmapWindow(ZafIChar *tBuff) : ZafWindow(0, 0, 25, 4)
{
	AddGenericObjects(new ZafStringData(tBuff));
	SetStringID(tBuff);
	SetLocked(true);

	// Add the animated bitmap object to the window.
	ZafAnimatedBitmap *bitmap = new ZafAnimatedBitmap(4, 1, 0, 0,
		ZAF_ITEXT("WORLD_"), 15, INITIAL_INTERVAL);
	bitmap->SetBordered(false);
	bitmap->SetStringID(ZAF_ITEXT("Bitmap"));
	Add(bitmap);
}

// All events are handled in the Event function.
ZafEventType ControlWindow::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 S_REGISTER_OBJECT:
		ccode = ZafWindow::Event(event);
		windowManager->screenID = screenID;
		break;

	case U_RESET_TIMER:
		{
		ZafWindowObject *object = GetObject(event.text);
		if (object)
			object->SetSelected(true);
		ResetScrollBar();
		delete [] event.text;
		}
		break;

	case U_ADJUST_TIMER:
		ResetTimerInterval();
		break;

	case U_OPEN_BITMAP:
		OpenBitmapWindow();
		break;

	case U_CLOSE_BITMAP:
		CloseBitmapWindow();
		break;

	case U_UPDATE_SCROLL:
		ResetScrollBar();
		break;

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

// Open a new ZafAnimatedBitmap window.
void ControlWindow::OpenBitmapWindow(void)
{
	bitmapCounter++;
	ZafIChar buff[ZAF_MAXNAMELEN];
	sprintf(buff, ZAF_ITEXT("Window %i"), bitmapCounter);

	ZafButton *button = new ZafButton(0, 0, 0, 0, buff);
	button->SetStringID(buff);
	button->SetSendMessageWhenSelected(true);
	button->SetValue(U_UPDATE_SCROLL);
	button->SetHzJustify(ZAF_HZ_LEFT);
	button->SetSelected(true);
	button->SetButtonType(ZAF_FLAT_BUTTON);
	bitmapCombo->Add(button);

	// Create the window and add the support objects.
	BitmapWindow *window = new BitmapWindow(buff);

	zafWindowManager->Add(window);
}

// Close the window shown in the combo.
void ControlWindow::CloseBitmapWindow(void)
{
	ZafIChar *currentBitmap = ZAF_NULLP(ZafIChar);
	ZafWindowObject *window = ZAF_NULLP(ZafWindow);

	ZafWindowObject *object = bitmapCombo->Current();
	if (object)
	{
		currentBitmap = strdup(object->Text());
		// Make the next or previous object current in the combo.
		ZafWindowObject *prevObject = object->Next() ?
			object->Next() : object->Previous();

		bitmapCombo->Subtract(object);
		delete object;

		if (prevObject)
			prevObject->SetSelected(true);
	}
	if (currentBitmap)
	{
		window = zafWindowManager->GetObject(currentBitmap);
		delete currentBitmap;
	}
	if (window)
	{
		zafWindowManager->Subtract(window);
		delete window;
	}
	return;
}

// Reset the timer for the window shown in the combo.
void ControlWindow::ResetTimerInterval(void)
{
	// Set up the stringID to get the bitmap object.
	ZafIChar buff[ZAF_MAXNAMELEN];
	bool noWindow = false;
	if (!bitmapCombo->Text())
		noWindow = true;
	else
		sprintf(buff, ZAF_ITEXT("%s%s"),	bitmapCombo->Text(), ZAF_ITEXT("~Bitmap"));

	// Get the current slider information.
	int interval = (int)slider->ScrollData()->Current();

	// Set the integer information.
	ZafIntegerData *intervalData = currentInterval->IntegerData();
	intervalData->SetInteger(MAX_INTERVAL - interval + MIN_INTERVAL);

	// Set the timer interval on the animated bitmap.
	ZafAnimatedBitmap *bitmap = 0;
	if (!noWindow)
		bitmap = DynamicPtrCast(zafWindowManager->GetObject(buff), ZafAnimatedBitmap);
	if (bitmap)
		bitmap->SetTimerInterval(MAX_INTERVAL - interval + MIN_INTERVAL);

	return;
}

// Reset the timer for the window shown in the combo.
void ControlWindow::ResetScrollBar()
{
	// Set up the stringID to get the bitmap object.
	ZafIChar buff[ZAF_MAXNAMELEN];
	sprintf(buff, ZAF_ITEXT("%s%s"), bitmapCombo->Text(), ZAF_ITEXT("~Bitmap"));

	// Get a pointer to the bitmap from the selected window.
	ZafAnimatedBitmap *bitmap =
		DynamicPtrCast(zafWindowManager->GetObject(buff), ZafAnimatedBitmap);

	// Make sure the object is valid.
	if (!bitmap)
		return;

	// Get the timer interval for the selected bitmap window.
	long interval = bitmap->TimerInterval();

	// Reset the scroll information.
	ZafScrollData *scrollData = slider->ScrollData();
	scrollData->SetCurrent(MAX_INTERVAL - interval + MIN_INTERVAL);

	// Reset the integer information.
	ZafIntegerData *intervalData = currentInterval->IntegerData();
	intervalData->SetInteger(interval);

	return;
}

ZafEventType BitmapWindow::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = LogicalEvent(event);
	switch(ccode)
	{
	case N_CURRENT:
		{
			ZafEventStruct tmpEvent(U_RESET_TIMER);
			tmpEvent.route = windowManager->GetObject("CONTROL_WINDOW");
			if (tmpEvent.route)
			{
				tmpEvent.text = strdup(StringID());
				eventManager->Put(tmpEvent);
			}
		}
		ccode = ZafWindow::Event(event);
		break;
		
	default:
		ccode = ZafWindow::Event(event);
	}
	return (ccode);
}
