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

#include <zaf.hpp>
#include <z_string.hpp>

// Define user events to be sent by menu items.
const ZafUserEvent USER_FILE_OPEN		= U_USER_FIRST;
const ZafUserEvent USER_WINDOW_SELECT	= U_USER_FIRST + 1;
const ZafUserEvent USER_HELP_ABOUT		= U_USER_FIRST + 2;

ZafEventType ExitFunction(ZafDisplay *, ZafEventManager *, ZafWindowManager *windowManager)
{
	if (windowManager)
	{
		ZafWindow *window = DynamicPtrCast(windowManager->First(), ZafWindow);
		while (window && window->Temporary())
			window = DynamicPtrCast(window->Next(), ZafWindow);

		if (window)
			return(window->Event(N_EXIT));
	}
		
	return (0);
}

// Image window is a ZafScrollWindow that allows viewing of images that
// are larger than the window.
class ImageWindow : public ZafScrolledWindow
{
public:
	ImageWindow(int left, int top, int width, int height, const ZafIChar *imageFileName);
	virtual ZafEventType Event(const ZafEventStruct &event);

protected:
	ZafImage *image;
};

ImageWindow::ImageWindow(int left, int top, int width, int height, const ZafIChar *imageFileName) :
	ZafScrolledWindow(left, top, width, height, 900, 600)	
{
	// Set coordinate to pixel so that SetScrollWidth() and SetScrollHeight()
	// will use pixel values.
	SetCoordinateType(ZAF_PIXEL);

	// Cause the image window to occupy the entire client area of its parent.
	SetRegionType(ZAF_AVAILABLE_REGION);
	
	// Add the scroll bars.
	Add(new ZafScrollBar(ZAF_CORNER_SCROLL));
	Add(new ZafScrollBar(ZAF_VERTICAL_SCROLL));
	Add(new ZafScrollBar(ZAF_HORIZONTAL_SCROLL));

	// Add a child image that computes its own size.
	image = new ZafImage(0, 0, 0, 0, imageFileName);
	image->SetAutoSize(true);
	Add(image);
}

ZafEventType ImageWindow::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;

	switch (ccode)
	{
	case S_COMPUTE_SIZE:
		// Set the scroll region based on the child image's size.
		ccode = ZafScrolledWindow::Event(event);
		image->Event(event);
		SetScrollWidth(image->zafRegion.Width());
		SetScrollHeight(image->zafRegion.Height());
		break;

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

	return (ccode);
}

// Control window is the MDI parent window that controls the application.
// It displays images in MDI child windows.  This is accomplished by
// adding ImageWindow objects to the MDI children.
class ControlWindow : public ZafMDIWindow
{
public:
	ControlWindow(void);

	virtual ZafWindowObject *Add(ZafWindowObject *object, ZafWindowObject *position = ZAF_NULLP(ZafWindowObject));
	virtual ZafWindowObject *Subtract(ZafWindowObject *object);
	virtual ZafEventType Event(const ZafEventStruct &event);

	void Open(const ZafIChar *imageFileName);

protected:
	ZafPullDownItem *windowMenu;
};

ControlWindow::ControlWindow(void) :
	ZafMDIWindow(0, 0, 70, 9, ZAF_MDI_PARENT)
{
	// Add the generic objects.
	AddGenericObjects(new ZafStringData("Control Window - (ZafMDIWindow)"));

	// Add a menu.
	ZafPullDownMenu *menu = new ZafPullDownMenu();
	ZafPullDownItem *item = new ZafPullDownItem(ZAF_ITEXT("File"));
	ZafPopUpItem *option = new ZafPopUpItem(ZAF_ITEXT("Open"));
	option->SetSendMessageWhenSelected(true);
	option->SetValue(USER_FILE_OPEN);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT("Close"));
	option->SetSendMessageWhenSelected(true);
	option->SetValue(S_MDI_CLOSE);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT(""), ZAF_SEPARATOR);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT(""), ZAF_EXIT_OPTION);
	item->Add(option);
	menu->Add(item);
	item = windowMenu = new ZafPullDownItem(ZAF_ITEXT("Window"));
	option = new ZafPopUpItem(ZAF_ITEXT("Cascade"));
	option->SetSendMessageWhenSelected(true);
	option->SetValue(S_MDI_CASCADE_WINDOWS);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT("Tile"));
	option->SetSendMessageWhenSelected(true);
	option->SetValue(S_MDI_TILE_WINDOWS);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT("Maximize"));
	option->SetSendMessageWhenSelected(true);
	option->SetValue(S_MDI_MAXIMIZE);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT("Minimize"));
	option->SetSendMessageWhenSelected(true);
	option->SetValue(S_MDI_MINIMIZE);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT("Close"));
	option->SetSendMessageWhenSelected(true);
	option->SetValue(S_MDI_CLOSE);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT("Restore"));
	option->SetSendMessageWhenSelected(true);
	option->SetValue(S_MDI_RESTORE);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT("Next Window"));
	option->SetSendMessageWhenSelected(true);
	option->SetValue(S_MDI_NEXT_WINDOW);
	item->Add(option);
	option = new ZafPopUpItem(ZAF_ITEXT(""), ZAF_SEPARATOR);
	item->Add(option);
	menu->Add(item);
	item = new ZafPullDownItem(ZAF_ITEXT("Help"));
	option = new ZafPopUpItem(ZAF_ITEXT("About"), ZAF_ABOUT_OPTION);
	option->SetSendMessageWhenSelected(true);
	option->SetValue(USER_HELP_ABOUT);
	item->Add(option);
	menu->Add(item);
	Add(menu);

	// Add a tool bar.
//	ZafToolBar *toolBar = new ZafToolBar(0, 0, 0, 1);
//	Add(toolBar);

	Add(new ZafScrollBar(ZAF_CORNER_SCROLL));
	Add(new ZafScrollBar(ZAF_VERTICAL_SCROLL));
	Add(new ZafScrollBar(ZAF_HORIZONTAL_SCROLL));

	// Open the intial images. (Creates MDI child windows)
	Open(ZAF_ITEXT("image1"));
	Open(ZAF_ITEXT("image2"));
	Open(ZAF_ITEXT("image3"));
}

ZafWindowObject *ControlWindow::Add(ZafWindowObject *object, ZafWindowObject *position)
{
	if (!object->SupportObject())
	{
		ZafPopUpItem *item = new ZafPopUpItem(object->Text());
		item->SetStringID(object->Text());
		item->userObject = object;
		item->SetSendMessageWhenSelected(true);
		item->SetValue(USER_WINDOW_SELECT);
		windowMenu->Add(item);
	}

	return (ZafMDIWindow::Add(object, position));
}

ZafWindowObject *ControlWindow::Subtract(ZafWindowObject *object)
{
	if (!object->SupportObject())
	{
		ZafWindowObject *item = windowMenu->GetObject(object->Text());
		windowMenu->Subtract(item);
		delete item;
	}

	return (ZafMDIWindow::Subtract(object));
}

void ControlWindow::Open(const ZafIChar *imageFileName)
{
	// Static values used to tile the windows.
	static int left = 2;
	static int top = 1;

	// Create the title text.
	ZafIChar titleText[256];
	sprintf(titleText, ZAF_ITEXT("Image Window (%s) - (ZafMDIWindow + ZafScrolledWindow)"), imageFileName);

	// Create the mdi child and add generic objects.
	ZafMDIWindow *mdiChild = new ZafMDIWindow(left++, top++, 40, 5, ZAF_MDI_CHILD);
	mdiChild->AddGenericObjects(new ZafStringData(titleText));

	// Add an image window to the MDI child.
	mdiChild->Add(new ImageWindow(0, 0, 0, 0, imageFileName));

	// Add the MDI child.
	Add(mdiChild);
}

ZafEventType ControlWindow::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;

	switch (ccode)
	{
	case USER_FILE_OPEN:
		{
		// Create a file dialog.
		ZafFileDialog fileDialog(5, 5, 66, 10);

		// Specify which files are to be shown in the dialog.
		fileDialog.SetFilter(ZafImage::defaultFilterName);

		// Open an image window with the selected file (if any).
		if (fileDialog.GetFile(ZAF_FILE_DIALOG_OPEN) == S_DLG_OK)
			Open(fileDialog.File());
		}
		break;

	case USER_WINDOW_SELECT:
		{
		ZafWindowObject *window = First();
		while (window && strcmp(window->Text(), event.windowObject->Text()) != 0)
			window = window->Next();
		if (window)
			window->SetFocus(true);
		}
		break;

	case USER_HELP_ABOUT:
		{
		// Create a dialog window.
		ZafDialogWindow dialogWindow(0, 0, 40, 5);

		// Add fields to the dialog window.
		dialogWindow.AddGenericObjects(new ZafStringData("About - (ZafDialogWindow)"));
		ZafPrompt *prompt = new ZafPrompt(0, 1, 40, ZAF_ITEXT("Zinc Application Framework"));
		prompt->SetHzJustify(ZAF_HZ_CENTER);
		prompt->SetFont(ZAF_FNT_SYSTEM);
		dialogWindow.Add(prompt);
		ZafButton *button = new ZafButton(15, 3, 10, 1, ZAF_ITEXT("OK"));
		button->SetSendMessageWhenSelected(true);
		button->SetValue(S_DLG_OK);
		dialogWindow.Add(button);

		// Show the dialog and wait for a response.
		windowManager->Center(&dialogWindow);
		dialogWindow.Control();
		}
		break;

//	case N_CLOSE:
	case N_EXIT:
		{
		// Create a message window.
		ZafMessageWindow messageWindow(ZAF_ITEXT("Exit? - (ZafMessageWindow)"),
			ZAF_HAND_ICON, ZAF_DIALOG_OK | ZAF_DIALOG_CANCEL,
			ZAF_DIALOG_CANCEL, ZAF_ITEXT("Application will terminate!"));

		// Get a response from the message window.
		if (messageWindow.Control() == S_DLG_OK)
			// Allow the window to be closed.
			ccode = 0;
		else
			// Prevent the window from being closed.
			ccode = S_ERROR;
		}
		break;

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

	return (ccode);
}

int ZafApplication::Main(void)
{
	LinkMain();

	// Create the MDI parent window.
	ZafWindow *controlWindow = new ControlWindow();

	// Set the exit function.
	zafWindowManager->SetExitFunction(ExitFunction);

	// Show the window on the screen.
	zafWindowManager->Center(controlWindow);
	zafWindowManager->Add(controlWindow);

	// Cause the application to exit if the control window is closed.
	zafWindowManager->screenID = controlWindow->screenID;

	Control();

	return (0);
}
