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

// This example program takes the light object created in draw2 and adds 
// several of them to a derived window that also has a Draw() funciton.  
// The derived window's Draw() function draws the form of a stop light.  
// Three light objects are then added to the window to look like the lights
// of a stop light.

#include <zaf.hpp>
#include "draw3.hpp"

// ----- STOPLIGHT WINDOW -------------------------------------------------------

StopLightWin::StopLightWin(int left, int top, int width, int height) :
	ZafWindow(left, top, width, height)
{
	// Create the button used to change the state of the stop light.
	ZafButton *button = new ZafButton(1, 12, 18, 1, new ZafStringData("Change Light State"));
	button->SetSendMessageWhenSelected(true);
	button->SetValue(CHANGE_LIGHT_STATE);

	// Add the objects to the window.
	AddGenericObjects(new ZafStringData("Stop Light Window"));
	Add(button);
	stopLight = new StopLight();
	Add(stopLight);

	// Make the stopLight noncurrent.
	stopLight->SetNoncurrent(false);

	// Center the Window.
	zafWindowManager->Center(this);
}

ZafEventType StopLightWin::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;
	switch(ccode)
	{
	case CHANGE_LIGHT_STATE:
		// Pass the event to the StopLight.
		stopLight->Event(event);
		break;
	default:
		ccode = ZafWindow::Event(event);
		break;
	}
	return(ccode);

}

// ----- STOPLIGHT  -------------------------------------------------------------

StopLight::StopLight() :
	ZafWindow(3, 1, 14, 10)
{
	// Add the lights to the StopLight
	red = new Light(4, 1, 6, 3, RED_LIGHT);
	yellow = new Light(4, 4, 6, 3, YELLOW_LIGHT);
	green = new Light(4, 7, 6, 3, GREEN_LIGHT);
	Add(red);
	Add(yellow);
	Add(green);

	// Turn the red light on.
	red->SetDisabled(false);
	// Set OSDraw to false so the StopLight Draw function will be called.
	SetOSDraw(false);
}

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType StopLight::Draw(const ZafEventStruct &event, ZafEventType ccode)
{
	ZafDisplay *display = Display();
	ZafRegionStruct drawRegion = BeginDraw();

	if (ccode == S_REDISPLAY_REGION)
		display->SetClipRegion(event.region);

	// Set the background color to darkgray and draw the stop light outline.
	display->SetBackground(ZAF_CLR_DARKGRAY);
	display->SetForeground(ZAF_CLR_DARKGRAY);
	display->Ellipse(drawRegion.left + display->cellWidth, 
		drawRegion.top + 1, drawRegion.right - display->cellWidth,
		drawRegion.top + 2 * display->cellHeight, 0, 180, 0, true);
	display->Rectangle(drawRegion.left + display->cellWidth, 
		drawRegion.top + display->cellHeight, drawRegion.right - display->cellWidth,
		drawRegion.bottom, 0, true);

	EndDraw();
	return (ccode);
}
#endif

ZafEventType StopLight::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;
	switch(ccode)
	{
	case CHANGE_LIGHT_STATE:
		// Find the active light, turn it off and turn on the next one.
		if (!red->Disabled())
		{
			red->Event(TURN_OFF);
			green->Event(TURN_ON);
		}
		else if (!green->Disabled())
		{
			green->Event(TURN_OFF);
			yellow->Event(TURN_ON);
		}
		else
		{
			yellow->Event(TURN_OFF);
			red->Event(TURN_ON);
		}
		break;
	default:
		ccode = ZafWindow::Event(event);
		break;
	}
	return(ccode);

}

// ----- Light Object -------------------------------------------------------

Light::Light(int left, int top, int width, int height, LightColor color) :
	ZafWindowObject(left, top, width, height)
{
	// Set the palette colors to be used.
	ZafPaletteStruct onPalette, offPalette;	
	if (color == RED_LIGHT)
	{
		onPalette.colorForeground = offPalette.colorForeground = ZAF_CLR_RED;
		onPalette.colorBackground = ZAF_CLR_LIGHTRED;
		offPalette.colorBackground = ZAF_CLR_RED;
	}
	else if (color == YELLOW_LIGHT)
	{
		onPalette.colorForeground = offPalette.colorForeground = ZAF_CLR_YELLOW;
		onPalette.colorBackground = ZAF_CLR_YELLOW;
		offPalette.colorBackground = ZAF_CLR_LIGHTGRAY;
	}
	else 
	{
		onPalette.colorForeground = offPalette.colorForeground = ZAF_CLR_GREEN;
		onPalette.colorBackground = ZAF_CLR_LIGHTGREEN;
		offPalette.colorBackground = ZAF_CLR_GREEN;
	}

	// Create a ZafPaletteData.
	SetUserPaletteData(new ZafPaletteData());

	// If disabled attribute is set to true the light is in the off state.
	// If disabled attribute is set	to false the light is in the on state.
	// Create the palette to be used when the light is off.
	ZafPaletteStruct drawPalette = userPaletteData->GetPalette(ZAF_PM_FOREGROUND,
		ZAF_PM_DISABLED);
	drawPalette.colorForeground = offPalette.colorForeground;
	drawPalette.colorBackground = offPalette.colorBackground;

	// Add the palette to the palette table.
	userPaletteData->AddPalette(ZAF_PM_FOREGROUND, ZAF_PM_DISABLED, drawPalette);
	
	// Create the palette to be used when the light is on.
	drawPalette = userPaletteData->GetPalette(ZAF_PM_FOREGROUND, ZAF_PM_ENABLED);
	drawPalette.colorForeground = onPalette.colorForeground;
	drawPalette.colorBackground = onPalette.colorBackground;

	// Add the palette to the palette table.
	userPaletteData->AddPalette(ZAF_PM_FOREGROUND, ZAF_PM_ENABLED, drawPalette);

	// Turn off the OSDraw so Draw() function will be called.
	SetOSDraw(false);
	// Set light's state to off, and make it noncurrent.
	SetDisabled(true);
	SetNoncurrent(true);
}

#if defined(ZAF_DEFAULT_DRAW)
ZafEventType Light::Draw(const ZafEventStruct &event, ZafEventType ccode)
{
	ZafDisplay *display = Display();
	ZafRegionStruct drawRegion = BeginDraw();

	if (ccode == S_REDISPLAY_REGION)
		display->SetClipRegion(event.region);
	// Draw the objcet background to match the stoplight.
	display->SetBackground(ZAF_CLR_DARKGRAY);
	display->Rectangle(drawRegion, 0, true);

	//Draw the light shade.
	display->SetBackground(ZAF_CLR_LIGHTGRAY);
	display->SetForeground(ZAF_CLR_LIGHTGRAY);
	int lightHeight = drawRegion.right - drawRegion.left - 2;

	display->Ellipse(drawRegion.left + 1, drawRegion.top + 1,
		drawRegion.right - 1, drawRegion.top + 1 + lightHeight, 
		0, 180, 0, true);
	
	display->SetBackground(ZAF_CLR_DARKGRAY);
	display->SetForeground(ZAF_CLR_DARKGRAY);	
	display->Ellipse(drawRegion.left, drawRegion.top + 7,
		drawRegion.right, drawRegion.top + 7 + lightHeight, 
		0, 180, 0, true);

	// Set the palette the light should be drawn with.
	display->SetPalette(LogicalPalette(ZAF_PM_FOREGROUND, PaletteState()));
	lightHeight = drawRegion.right - drawRegion.left - 4;

	// The Light is an ellipse.
	display->Ellipse(drawRegion.left + 2, drawRegion.top + 
		(display->cellHeight >> 1), drawRegion.right - 2, 
		drawRegion.top + (display->cellHeight >> 1) + lightHeight, 
		0, 360, 2, true);

	EndDraw();
	return (ccode);
}
#endif

ZafEventType Light::Event(const ZafEventStruct &event)
{
	ZafEventType ccode = event.type;
	switch(ccode)
	{
	case TURN_ON:
		// Turn the light on.
		SetDisabled(false);
		Redisplay();
		break;
	case TURN_OFF:
		// Turn the light off.
		SetDisabled(true);
		Redisplay();
		break;
	default:
		ccode = ZafWindowObject::Event(event);
		break;
	}
	return(ccode);

}

// ----- Main() -------------------------------------------------------------

int ZafApplication::Main(void)
{
	// Ensure main() is linked properly.
	LinkMain();

	// Create and add the StopLight window.
	zafWindowManager->Add(new StopLightWin(0, 0, 20, 14));

	// Get the user input.
	Control();

	// Return success.
	return (0);
}

