/******************************************************************************
 JXDirector.cc

	Stores a list of directors.

	BASE CLASS = virtual JBroadcaster

	Copyright © 1996 by John Lindal. All rights reserved.

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

#include <JXDirector.h>
#include <jAssert.h>

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

	supervisor can be NULL, but only JXApplication should do this because
	everybody else should be owned by somebody (the application, at least).

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

JXDirector::JXDirector
	(
	JXDirector* supervisor
	)
	:
	JBroadcaster()
{
	itsSupervisor   = supervisor;
	itsSubDirectors = NULL;
	itsActiveFlag   = kFalse;
	itsSuspendCount = 0;
	itsClosingFlag  = kFalse;

	if (itsSupervisor != NULL)
		{
		itsSupervisor->AddDirector(this);
		}
}

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

	Close() should be called first.

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

JXDirector::~JXDirector()
{
	assert( itsClosingFlag );
	assert( itsSubDirectors == NULL );

	if (itsSupervisor != NULL)
		{
		itsSupervisor->RemoveDirector(this);
		}
}

/******************************************************************************
 IsWindowDirector (virtual)

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

JBoolean
JXDirector::IsWindowDirector()
	const
{
	return kFalse;
}

/******************************************************************************
 Close (virtual)

	Close all sub-directors and delete ourselves.

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

JBoolean
JXDirector::Close()
{
	assert( !itsClosingFlag );
	itsClosingFlag = kTrue;

	while (itsSubDirectors != NULL && !itsSubDirectors->IsEmpty())
		{
		JXDirector* theDirector = itsSubDirectors->FirstElement();
		if (!theDirector->Close())
			{
			itsClosingFlag = kFalse;
			return kFalse;
			}
		else if (itsSubDirectors != NULL &&
				 theDirector == itsSubDirectors->FirstElement())
			{
			// Since one JXDocument can keep another one open,
			// if the owned document is in front, we have to shove it to
			// the end so we close the owner first.

			itsSubDirectors->MoveElementToIndex(1, itsSubDirectors->GetElementCount());
			}
		}

	// falling through means everybody is closed

	delete this;
	return kTrue;
}

/******************************************************************************
 Activate (virtual)

	We do not propagate the Activate message to subdirectors because
	each derived class must decide whether or not this is appropriate.

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

void
JXDirector::Activate()
{
	itsActiveFlag = kTrue;
}

/******************************************************************************
 Deactivate (virtual)

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

JBoolean
JXDirector::Deactivate()
{
	if (itsActiveFlag && itsSubDirectors != NULL)
		{
		const JSize dirCount = itsSubDirectors->GetElementCount();
		for (JIndex i=1; i<=dirCount; i++)
			{
			if (!(itsSubDirectors->NthElement(i))->Deactivate())
				{
				return kFalse;
				}
			}
		}
	itsActiveFlag = kFalse;
	return kTrue;
}

/******************************************************************************
 Suspend (virtual)

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

void
JXDirector::Suspend()
{
	if (itsSubDirectors != NULL)
		{
		const JSize dirCount = itsSubDirectors->GetElementCount();
		for (JIndex i=1; i<=dirCount; i++)
			{
			(itsSubDirectors->NthElement(i))->Suspend();
			}
		}
	itsSuspendCount++;
}

/******************************************************************************
 Resume (virtual)

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

void
JXDirector::Resume()
{
	if (itsSuspendCount > 0)
		{
		itsSuspendCount--;
		}

	if (itsSubDirectors != NULL)
		{
		const JSize dirCount = itsSubDirectors->GetElementCount();
		for (JIndex i=1; i<=dirCount; i++)
			{
			(itsSubDirectors->NthElement(i))->Resume();
			}
		}
}

/******************************************************************************
 AddDirector (private)

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

void
JXDirector::AddDirector
	(
	JXDirector* theDirector
	)
{
	if (itsSubDirectors == NULL)
		{
		itsSubDirectors = new JPtrArray<JXDirector>;
		assert( itsSubDirectors != NULL );
		}

	if (!itsSubDirectors->Includes(theDirector))
		{
		itsSubDirectors->Append(theDirector);
		}
}

/*****************************************************************************
 RemoveDirector (private)

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

void
JXDirector::RemoveDirector
	(
	JXDirector* theDirector
	)
{
	if (itsSubDirectors != NULL)
		{
		itsSubDirectors->Remove(theDirector);
		if (itsSubDirectors->IsEmpty())
			{
			delete itsSubDirectors;
			itsSubDirectors = NULL;
			}
		DirectorClosed(theDirector);
		}
}

/*****************************************************************************
 DirectorClosed (virtual protected)

	The only safe way to know whether a subdirector still exists is
	to listen for this message.

	One does not need this for dialogs because they close immediately
	after broadcasting the Deactivated message.

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

void
JXDirector::DirectorClosed
	(
	JXDirector* theDirector
	)
{
}

#include <JArray.tmpls>
#define JTemplateType JXDirector
#include <JPtrArray.tmpls>
#undef JTemplateType
