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

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

struct StudentRecord
{
	ZafIChar name[32];
	ZafIChar finalGrade[4];
	int homework;
	int tests;
	int final;
};

struct SampleData
{
	ZafIChar *name;
	ZafIChar *finalGrade;
	int homework;
	int tests;
	int final;
} sampleData[] =
{
	{ ZAF_ITEXT("Curly"), ZAF_ITEXT("F"), 17, 35, 3 },
	{ ZAF_ITEXT("Einstein, Albert"), ZAF_ITEXT("B"), 50, 85, 98 },
	{ ZAF_ITEXT("Fool, Big"), ZAF_ITEXT("A"), 100, 95, 85 },
	{ ZAF_ITEXT("Mo"), ZAF_ITEXT("F"), 12, 20, 11},
	{ ZAF_NULLP(ZafIChar), ZAF_NULLP(ZafIChar), 0, 0, 0 },
};

// ----- SampleTable --------------------------------------------------------

class SampleTable : public ZafTable
{
public:
	SampleTable(SimpleDatabase *database);

	ZafError ReadRecordData(ZafTableRecord &record, ZafWindowObject *row);
	ZafError WriteRecordData(ZafTableRecord &record, ZafWindowObject *row);

private:
	SimpleDatabase *database;
};

SampleTable::SampleTable(SimpleDatabase *setDatabase) :
	ZafTable(0, 0, 0, 0, 5, 1, 1),
	database(setDatabase)
{
	// Set attributes.
	SetRegionType(ZAF_AVAILABLE_REGION);

	// Add Columns
	Add(new ZafString(0, 0, 20, ZAF_NULLP(ZafIChar), 32), ZAF_ITEXT("Name"));
	Add(new ZafInteger(20, 0, 7), ZAF_ITEXT("Homework"));
	Add(new ZafInteger(27, 0, 7), ZAF_ITEXT("Tests"));
	Add(new ZafInteger(34, 0, 7), ZAF_ITEXT("Final"));
	Add(new ZafString(41, 0, 11), ZAF_ITEXT("Final Grade"));

	// Add the scroll-bar.
	Add(new ZafScrollBar(ZAF_CORNER_SCROLL));
	Add(new ZafScrollBar(ZAF_VERTICAL_SCROLL));
	Add(new ZafScrollBar(ZAF_HORIZONTAL_SCROLL));

	// Set the number of records.
	maxOffset = database->Records() - 1;
}

ZafError SampleTable::ReadRecordData(ZafTableRecord &record, ZafWindowObject *rowField)
{
	ZafIChar recordNumText[16];
	sprintf(recordNumText, ZAF_ITEXT("%ld"), record.Offset());
	rowField->SetText(recordNumText);

	StudentRecord studentRecord;
	database->SeekRandomRecord(record.Offset(), &studentRecord);

	record(0)->SetText(studentRecord.name);
	DynamicPtrCast(record(1), ZafInteger)->IntegerData()->SetInteger(studentRecord.homework);
	DynamicPtrCast(record(2), ZafInteger)->IntegerData()->SetInteger(studentRecord.tests);
	DynamicPtrCast(record(3), ZafInteger)->IntegerData()->SetInteger(studentRecord.final);
	record(4)->SetText(studentRecord.finalGrade);

	return (ZAF_ERROR_NONE);
}

ZafError SampleTable::WriteRecordData(ZafTableRecord &record, ZafWindowObject *)
{
	StudentRecord studentRecord;
	strcpy(studentRecord.name, record(0)->Text());
	studentRecord.homework = (int)DynamicPtrCast(record(1), ZafInteger)->IntegerData()->Value();
	studentRecord.tests = (int)DynamicPtrCast(record(2), ZafInteger)->IntegerData()->Value();
	studentRecord.final = (int)DynamicPtrCast(record(3), ZafInteger)->IntegerData()->Value();
	strcpy(studentRecord.finalGrade, record(4)->Text());

	database->ModifyRecord(record.Offset(), &studentRecord);

	return (ZAF_ERROR_NONE);
}

// ----- SampleTableWindow --------------------------------------------------

const ZafUserEvent INSERT_RECORD	= U_USER_FIRST;
const ZafUserEvent DELETE_RECORD	= U_USER_FIRST + 1;

class SampleTableWindow : public ZafWindow
{
public:
	SampleTableWindow(int left, int top, int width, int height);
	virtual ~SampleTableWindow(void);

	ZafEventType Event(const ZafEventStruct &event);

protected:
	SimpleDatabase *database;
	ZafTable *table;
};

SampleTableWindow::SampleTableWindow(int left, int top, int width, int height) :
	ZafWindow(left, top, width, height)
{
	AddGenericObjects(new ZafStringData("Database Table"));

	ZafPullDownMenu *pullDownMenu = new ZafPullDownMenu();
	ZafPullDownItem *pullDownItem = new ZafPullDownItem(ZAF_ITEXT("File"));
	ZafPopUpItem *option = new ZafPopUpItem(ZAF_ITEXT(""), ZAF_EXIT_OPTION);
	pullDownItem->Add(option);
	pullDownMenu->Add(pullDownItem);
	Add(pullDownMenu);

	ZafToolBar *toolbar = new ZafToolBar(0, 0, 0, 1);

	ZafButton *button = new ZafButton(0, 0, 10, 1, ZAF_ITEXT("Insert"));
	button->SetSendMessageWhenSelected(true);
	button->SetValue(INSERT_RECORD);
	toolbar->Add(button);

	button = new ZafButton(0, 0, 10, 1, ZAF_ITEXT("Delete"));
	button->SetSendMessageWhenSelected(true);
	button->SetValue(DELETE_RECORD);
	toolbar->Add(button);

	Add(toolbar);

	// Initialize the database.
	database = new SimpleDatabase(sizeof(StudentRecord));
	for (int index = 0; sampleData[index].name; index++)
	{
		StudentRecord studentRecord;
		strcpy(studentRecord.name, sampleData[index].name);
		strcpy(studentRecord.finalGrade, sampleData[index].finalGrade);
		studentRecord.homework = sampleData[index].homework;
		studentRecord.tests = sampleData[index].tests;
		studentRecord.final = sampleData[index].final;
		database->AddRecord(&studentRecord);
	}

	table = new SampleTable(database);
	Add(table);
}

SampleTableWindow::~SampleTableWindow(void)
{
	delete database;
}

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

	switch (ccode)
	{
	case INSERT_RECORD:
		{
		ZafOffset insertOffset = table->FocusOffset();
		StudentRecord newStudentRecord;
		strcpy(newStudentRecord.name, ZAF_ITEXT("New Student"));
		newStudentRecord.finalGrade[0] = 0;
		newStudentRecord.homework = 0;
		newStudentRecord.tests = 0;
		newStudentRecord.final = 0;
		table->Flush();
		database->AddRecord(&newStudentRecord, insertOffset);
		table->InsertRecord(insertOffset);
		}
		break;

	case DELETE_RECORD:
		{
		ZafOffset deleteOffset = table->FocusOffset();
		if (deleteOffset > -1)
		{
			table->Flush();
			database->DeleteRecord(deleteOffset);
			table->DeleteRecord(deleteOffset);
		}
		}
		break;

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

	return(ccode);
}

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

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

	ZafWindow *window = new SampleTableWindow(0, 0, 60, 15);

	window->SetVisible(false);
	zafWindowManager->Add(window);
	zafWindowManager->Center(window);
	window->SetVisible(true);

	Control();

	// Return success.
	return (0);
}

