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

#include <zaf.hpp>
#include <cf_api/bz_zcht.hpp> // ChartFolio header for ZafChart

void PrintObject(ZafWindowObject *object, int left, int top,
	int width, int height, ZafCoordinateType coordinateType,
	ZafPrinter *printer)
{
	// Get the print region in pixel coordinates. (pixel coordinates are used 
	// for compatibilitey between the display and the printer.)
	ZafRegionStruct printRegion;
	printRegion.coordinateType = ZAF_PIXEL;
	printRegion.left = (int)printer->ConvertXValue(left, coordinateType, ZAF_PIXEL);
	printRegion.top = (int)printer->ConvertYValue(top, coordinateType, ZAF_PIXEL);
	printRegion.right = (int)(printRegion.left + printer->ConvertXValue(width, coordinateType, ZAF_PIXEL) - 1);
	printRegion.bottom = (int)(printRegion.top + printer->ConvertYValue(height, coordinateType, ZAF_PIXEL) - 1);

	// Create an invisible container window to hold the modified object 
	// while printing.
	ZafWindow *containerWindow = new ZafWindow(0, 0, 0, 0);
	containerWindow->SetVisible(false);
	zafWindowManager->Add(containerWindow);

// Duplicate() could be used to simplify this function, but Duplicate() is
// currently broken for ZafChart.

	// Remove the object from its normal parent.
	ZafWindow *parent = DynamicPtrCast(object->parent, ZafWindow);
	if (parent)
		parent->Subtract(object);

	// Set the object's "print" region.
	ZafRegionStruct saveRegion = object->Region();
	object->SetRegion(printRegion);

	// Add the object to its invisible container.  (This initializes the
	// object in preparation for printing.)
	containerWindow->Add(object);

	// Set the object's display to the printer.
	ZafDisplay *saveDisplay = object->display;
	object->display = printer;

	// Set the printer's coordinate type to ZAF_PIXEL so that it is 
	// compatible with the display.
	ZafCoordinateType saveCoordianteType = printer->SetCoordinateType(ZAF_PIXEL);

	// Get the object's "draw" region.
	ZafRegionStruct drawRegion = object->BeginDraw();

	// Set the printers origin to be compatible with the object.  (The 
	// object's "draw" region is environment dependant.) 
	ZafCoordinate oldOriginX = 0, oldOriginY = 0;
	printer->Origin(oldOriginX, oldOriginY);
	printer->SetOrigin(object->zafRegion.left - drawRegion.left, object->zafRegion.top - drawRegion.top);

	// Draw the object.
	object->Draw(ZafEventStruct(S_REDISPLAY), S_REDISPLAY);

	// End the objects draw operation.
	object->EndDraw();

	// Restore the printer's properties.
	printer->SetOrigin(oldOriginX, oldOriginY);
	printer->SetCoordinateType(saveCoordianteType);

	// Restore the object.
	object->display = saveDisplay;
	containerWindow->Subtract(object);
	object->SetRegion(saveRegion);
	if (parent)
		parent->Add(object);

	// Clean up.
	zafWindowManager->Subtract(containerWindow);
	delete containerWindow;
}

int ZafApplication::Main()
{
	const int DATA_GROUPS = 5;
	const int DATA_POINTS = 10;

	double chartData[DATA_GROUPS][DATA_POINTS] =
	{
		{ 20.0, 10.0, 20.0, 10.0, 20.0, 10.0, 20.0, 10.0, 20.0, 10.0 },
		{ 20.0, 18.0, 14.0, 2.0, 14.0, 37.0, 35.0, 30.0, 24.0, 23.0 },
		{ 33.0, 30.0, 27.0, 24.0, 21.0, 18.0, 15.0, 12.0, 9.0, 6.0 },
		{ 20.0, 15.0, 10.0, 12.0, 14.0, 20.0, 24.0, 28.0, 30.0, 32.0 },
		{ 16.0, 15.0, 23.0, 17.0, 24.0, 20.0, 18.0, 13.0, 28.0, 16.0 }
	};

	ZafChart *chart = new ZafChart(33, 7 ,33, 7, CF_ID_STACK_2D, CF_ID_YVALS_ON_NAT_NS);
	for (int i = 0; i < DATA_GROUPS; i++)
	{
		// Add the one-based data group.
		chart->AddDataGroup(i + 1);
		for (int j = 0; j < DATA_POINTS; j++)
			chart->AddDataPoint(i + 1, chartData[i][j]);
	}

	// Begin the print job.
	ZafPrinter printer;
	printer.BeginJob(ZAF_ITEXT("Print Object"));
	printer.BeginPage();

	// Draw the chart.
	PrintObject(chart, 1000, 1000, 3500, 3500, ZAF_INCH_1000, &printer);

	// Draw a rectangle around the chart.
	printer.SetForeground(ZAF_CLR_BLACK);
	printer.SetBackground(ZAF_CLR_WHITE);
	printer.SetCoordinateType(ZAF_INCH_1000);
	printer.Rectangle(1000, 1000, 4500, 4500);

	// End the print job.
	printer.EndPage();
	printer.EndJob();

	return (0);
}
