#ifndef _T_JAuxTableData
#define _T_JAuxTableData

/******************************************************************************
 JAuxTableData.tmpl

	Template for storing auxilliary data for a table.

	*** We depend on a JTable object rather than a JTableData object
		because JTable can guarantee that we get to update ourselves
		before any redraws.

	*** Since JRunArray is used to store the data, only intrinsic types
		can be stored, not objects.

	BASE CLASS = JPackedTableData<T>

	Copyright © 1996 by John Lindal. All rights reserved.

 ******************************************************************************/

#include <JAuxTableData.h>
#include <JTable.h>
#include <jAssert.h>

/******************************************************************************
 Constructor

 ******************************************************************************/

template <class T>
JAuxTableData<T>::JAuxTableData
	(
	JTable*		table,
	const T&	defValue
	)
	:
	JPackedTableData<T>(defValue)
{
	JAuxTableDataX(table);
}

// private

template <class T>
void
JAuxTableData<T>::JAuxTableDataX
	(
	JTable* table
	)
{
	itsTable = table;
	AdjustToTable();
	itsTable->RegisterAuxData(this);
	ListenTo(itsTable);
}

/******************************************************************************
 Copy constructor

 ******************************************************************************/

template <class T>
JAuxTableData<T>::JAuxTableData
	(
	JTable*					table,
	const JAuxTableData<T>&	source
	)
	:
	JPackedTableData<T>(source)
{
	JAuxTableDataX(table);
}

#ifdef __VCPP__

template <class T>
JAuxTableData<T>::JAuxTableData
	(
	const JAuxTableData<T>& source
	)
	:
	JPackedTableData<T>(source)
{
	assert( 0 /* only exists to keep Visual C++ happy */ );
}

#endif

/******************************************************************************
 Destructor

 ******************************************************************************/

template <class T>
JAuxTableData<T>::~JAuxTableData()
{
	itsTable->RemoveAuxData(this);
}

/******************************************************************************
 GetTable

 ******************************************************************************/

template <class T>
JTable*
JAuxTableData<T>::GetTable()
	const
{
	return itsTable;
}

/******************************************************************************
 Receive (virtual protected)

	Update our data to match the JTable that we belong to.
	RectChanged, RowChanged, ColChanged do not matter to us.

 ******************************************************************************/

template <class T>
void
JAuxTableData<T>::Receive
	(
	JBroadcaster*					sender,
	const JBroadcaster::Message&	message
	)
{
	// rows changed

	if (sender == itsTable && message.Is(JTableData::kRowInserted))
		{
		const JTableData::RowInserted* info =
			dynamic_cast(const JTableData::RowInserted*, &message);
		assert( info != NULL );
		InsertRow(info->GetIndex());
		}

	else if (sender == itsTable && message.Is(JTableData::kRowDuplicated))
		{
		const JTableData::RowDuplicated* info =
			dynamic_cast(const JTableData::RowDuplicated*, &message);
		assert( info != NULL );
		DuplicateRow(info->GetOrigIndex(), info->GetNewIndex());
		}

	else if (sender == itsTable && message.Is(JTableData::kRowRemoved))
		{
		const JTableData::RowRemoved* info =
			dynamic_cast(const JTableData::RowRemoved*, &message);
		assert( info != NULL );
		RemoveRow(info->GetIndex());
		}

	else if (sender == itsTable && message.Is(JTableData::kAllRowsRemoved))
		{
		RemoveAllRows();
		}

	else if (sender == itsTable && message.Is(JTableData::kRowMoved))
		{
		const JTableData::RowMoved* info =
			dynamic_cast(const JTableData::RowMoved*, &message);
		assert( info != NULL );
		MoveRow(info->GetOrigIndex(), info->GetNewIndex());
		}

	// columns changed

	else if (sender == itsTable && message.Is(JTableData::kColInserted))
		{
		const JTableData::ColInserted* info =
			dynamic_cast(const JTableData::ColInserted*, &message);
		assert( info != NULL );
		InsertCol(info->GetIndex());
		}

	else if (sender == itsTable && message.Is(JTableData::kColDuplicated))
		{
		const JTableData::ColDuplicated* info =
			dynamic_cast(const JTableData::ColDuplicated*, &message);
		assert( info != NULL );
		DuplicateCol(info->GetOrigIndex(), info->GetNewIndex());
		}

	else if (sender == itsTable && message.Is(JTableData::kColRemoved))
		{
		const JTableData::ColRemoved* info =
			dynamic_cast(const JTableData::ColRemoved*, &message);
		assert( info != NULL );
		RemoveCol(info->GetIndex());
		}

	else if (sender == itsTable && message.Is(JTableData::kAllColsRemoved))
		{
		RemoveAllCols();
		}

	else if (sender == itsTable && message.Is(JTableData::kColMoved))
		{
		const JTableData::ColMoved* info =
			dynamic_cast(const JTableData::ColMoved*, &message);
		assert( info != NULL );
		MoveCol(info->GetOrigIndex(), info->GetNewIndex());
		}

	// everything changed

	else if (sender == itsTable && message.Is(JTable::kTableDataChanged))
		{
		AdjustToTable();
		}

	// something else

	else
		{
		JPackedTableData<T>::Receive(sender, message);
		}
}

/******************************************************************************
 AdjustToTable (private)

	This resets every cell to its default value.

 ******************************************************************************/

template <class T>
void
JAuxTableData<T>::AdjustToTable()
{
	if (itsTable != NULL)
		{
		const JSize tableRowCount = itsTable->GetRowCount();
		while (GetRowCount() < tableRowCount)
			{
			AppendRow();
			}
		while (GetRowCount() > tableRowCount)
			{
			RemoveRow(1);
			}

		const JSize tableColCount = itsTable->GetColCount();
		while (GetColCount() < tableColCount)
			{
			AppendCol();
			}
		while (GetColCount() > tableColCount)
			{
			RemoveCol(1);
			}

		ClearAllElements();
		}
	else
		{
		RemoveAllRows();
		RemoveAllCols();
		}
}

#endif

// Instantiate the template for the specified type.

#if defined JTemplateType && ! defined JOnlyWantTemplateDefinition
	#define JTemplateName JAuxTableData
	#include <instantiate_template.h>
	#undef JTemplateName
#endif
