/******************************************************************************
 JXXFontMenu.cc

	Since we have to update our index before anybody can request its new
	value, the correct way to use this object is to listen for the
	FontChanged message, not the ItemSelected message.  In addition, since
	we are responsible for marking the menu item, clients should listen
	for FontNeedsUpdate instead of NeedsUpdate.

	BASE CLASS = JXTextMenu

	Copyright © 1996 by John Lindal. All rights reserved.

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

#include <JXXFontMenu.h>
#include <JXFontManager.h>
#include <JString.h>
#include <jAssert.h>

// JBroadcaster message types

const JCharacter* JXXFontMenu::kFontNeedsUpdate = "FontNeedsUpdate::JXXFontMenu";
const JCharacter* JXXFontMenu::kFontChanged     = "FontChanged::JXXFontMenu";

/******************************************************************************
 Constructor function (static)

	By forcing everyone to use this function, we avoid having to worry
	about not finding any fonts to match the given regex.

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

JBoolean
JXXFontMenu::Create
	(
	const JRegex&		regex,
	JSortXFontNamesFn	compare,
	const JCharacter*	title,
	JXContainer*		enclosure,
	const HSizingOption	hSizing,
	const VSizingOption	vSizing,
	const JCoordinate	x,
	const JCoordinate	y,
	const JCoordinate	w,
	const JCoordinate	h,
	JXXFontMenu**		menu
	)
{
	*menu = NULL;

	JPtrArray<JString> fontNames;
	(enclosure->GetXFontManager())->GetXFontNames(regex, &fontNames, compare);
	if (!fontNames.IsEmpty())
		{
		*menu = new JXXFontMenu(fontNames, title, enclosure, hSizing, vSizing, x,y, w,h);
		assert( *menu != NULL );
		(**menu).BuildMenu(fontNames);
		}

	fontNames.DeleteAll();
	return JConvertToBoolean( *menu != NULL );
}

JBoolean
JXXFontMenu::Create
	(
	const JRegex&		regex,
	JSortXFontNamesFn	compare,
	JXMenu*				owner,
	const JIndex		itemIndex,
	JXContainer*		enclosure,
	JXXFontMenu**		menu
	)
{
	*menu = NULL;

	JPtrArray<JString> fontNames;
	(enclosure->GetXFontManager())->GetXFontNames(regex, &fontNames, compare);
	if (!fontNames.IsEmpty())
		{
		*menu = new JXXFontMenu(fontNames, owner, itemIndex, enclosure);
		assert( *menu != NULL );
		(**menu).BuildMenu(fontNames);
		}

	fontNames.DeleteAll();
	return JConvertToBoolean( *menu != NULL );
}

/******************************************************************************
 Constructor (protected)

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

JXXFontMenu::JXXFontMenu
	(
	const JPtrArray<JString>&	fontNames,
	const JCharacter*			title,
	JXContainer*				enclosure,
	const HSizingOption			hSizing,
	const VSizingOption			vSizing,
	const JCoordinate			x,
	const JCoordinate			y,
	const JCoordinate			w,
	const JCoordinate			h
	)
	:
	JXTextMenu(title, enclosure, hSizing, vSizing, x,y, w,h)
{
	itsBroadcastFontChangeFlag = kTrue;
//	BuildMenu(fontNames);	// egcs thunks
}

JXXFontMenu::JXXFontMenu
	(
	const JPtrArray<JString>&	fontNames,
	JXMenu*						owner,
	const JIndex				itemIndex,
	JXContainer*				enclosure
	)
	:
	JXTextMenu(owner, itemIndex, enclosure)
{
	itsBroadcastFontChangeFlag = kTrue;
//	BuildMenu(fontNames);	// egcs thunks
}

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

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

JXXFontMenu::~JXXFontMenu()
{
}

/******************************************************************************
 GetFontID

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

JFontID
JXXFontMenu::GetFontID()
	const
{
	const JXFontManager* fontMgr = GetXFontManager();
	const JString& fontName      = GetFontName();

	JFontID id;
	const JBoolean ok = fontMgr->GetFontID(fontName, &id);
	assert( ok );

	return id;
}

/******************************************************************************
 SetFontName

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

void
JXXFontMenu::SetFontName
	(
	const JCharacter* name
	)
{
	const JIndex count = GetItemCount();
	for (JIndex i=1; i<=count; i++)
		{
		if (GetItemText(i) == name)
			{
			itsFontIndex = i;
			SetPopupChoice(itsFontIndex);
			if (itsBroadcastFontChangeFlag)
				{
				Broadcast(FontChanged());
				}
			break;
			}
		}
}

/******************************************************************************
 BuildMenu (private)

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

void
JXXFontMenu::BuildMenu
	(
	const JPtrArray<JString>& fontNames
	)
{
	RemoveAllItems();

	const JXFontManager* fontMgr = GetXFontManager();

	const JSize count = fontNames.GetElementCount();
	assert( count > 0 );
	for (JIndex i=1; i<=count; i++)
		{
		const JString* fontName = fontNames.NthElement(i);
		AppendItem(*fontName, kTrue, kTrue);

		JFontID id;
		const JBoolean ok = fontMgr->GetFontID(*fontName, &id);
		assert( ok );
		SetItemFont(i, id, 10, JFontStyle());	// size and style are irrelevant
		}

	SetUpdateAction(kDisableNone);

	SetFontName(*(fontNames.FirstElement()));
	ListenTo(this);
}

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

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

void
JXXFontMenu::Receive
	(
	JBroadcaster*	sender,
	const Message&	message
	)
{
	if (sender == this && message.Is(JXMenu::kNeedsUpdate))
		{
		itsBroadcastFontChangeFlag = kFalse;
		Broadcast(FontNeedsUpdate());
		CheckItem(itsFontIndex);
		itsBroadcastFontChangeFlag = kTrue;
		}
	else if (sender == this && message.Is(JXMenu::kItemSelected))
		{
		const JXMenu::ItemSelected* selection =
			dynamic_cast(const JXMenu::ItemSelected*, &message);
		assert( selection != NULL );
		itsFontIndex = selection->GetIndex();
		Broadcast(FontChanged());
		}

	else
		{
		JXTextMenu::Receive(sender, message);
		}
}

/******************************************************************************
 SetToPopupChoice

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

void
JXXFontMenu::SetToPopupChoice
	(
	const JBoolean isPopup
	)
{
	JXTextMenu::SetToPopupChoice(isPopup, itsFontIndex);
}
