/******************************************************************************
 JXMenuBar.cc

	Maintains a menu bar of pull-down menus.

	*** RemoveMenu() only removes the specified menu from the menu bar.
		It does -not- delete the JXMenu object.  It returns a pointer to
		it so the caller can delete it.  This is useful if one wants to
		dynamically add and remove menus from a menu bar without rebuilding
		the menu each time it is added.  (i.e. Use InsertMenu() to put the
		JXMenu back into the menu bar later.)  To remove a menu from the
		menu bar and throw it away, use DeleteMenu().

	*** Conversely, after calling InsertMenu(), the menu bar owns the
		JXMenu object and is responsible for deleting it.

	BASE CLASS = JXWidget

	Copyright © 1996 by John Lindal. All rights reserved.

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

#include <JXMenuBar.h>
#include <JXTextMenu.h>
#include <JXWindowPainter.h>
#include <jXPainterUtil.h>
#include <jXConstants.h>
#include <jAssert.h>

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

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

JXMenuBar::JXMenuBar
	(
	JXContainer*		enclosure,
	const HSizingOption	hSizing,
	const VSizingOption	vSizing,
	const JCoordinate	x,
	const JCoordinate	y,
	const JCoordinate	w,
	const JCoordinate	h
	)
	:
	JXWidget(enclosure, hSizing, vSizing, x,y, w,h)
{
	itsMenus = new JPtrArray<JXMenu>;
	assert( itsMenus != NULL );

	SetBorderWidth(kJXDefaultBorderWidth);
}

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

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

JXMenuBar::~JXMenuBar()
{
	const JSize count = itsMenus->GetElementCount();
	for (JIndex i=1; i<=count; i++)
		{
		JXMenu* theMenu = itsMenus->NthElement(i);
		assert( theMenu->itsOwner == NULL );
		theMenu->itsMenuBar = NULL;
		delete theMenu;
		}

	delete itsMenus;
}

/******************************************************************************
 InsertMenu

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

JXTextMenu*
JXMenuBar::InsertTextMenu
	(
	const JIndex		index,
	const JCharacter*	title
	)
{
	const JRect bounds = GetBounds();
	JXTextMenu* theMenu = new JXTextMenu(title, this, kFixedLeft, kVElastic,
										 bounds.left,bounds.top, 10,bounds.height());
	assert( theMenu != NULL );

	InsertMenu(index, theMenu);
	return theMenu;
}

JXTextMenu*
JXMenuBar::InsertTextMenu
	(
	const JIndex	index,
	JXImage*		image,
	const JBoolean	menuOwnsImage
	)
{
	const JRect bounds = GetBounds();
	JXTextMenu* theMenu =
		new JXTextMenu(image, menuOwnsImage, this, kFixedLeft, kVElastic,
					   bounds.left,bounds.top, 10,bounds.height());
	assert( theMenu != NULL );

	InsertMenu(index, theMenu);
	return theMenu;
}

void
JXMenuBar::InsertMenu
	(
	const JIndex	index,
	JXMenu*			theMenu
	)
{
	assert( theMenu != NULL );

	JIndex origIndex;
	if (itsMenus->Find(theMenu, &origIndex))
		{
		if (origIndex == index)
			{
			return;
			}
		RemoveMenu(origIndex);
		}

	theMenu->SetSizing(kFixedLeft, kVElastic);

	const JRect bounds = GetBounds();
	JCoordinate left   = bounds.left;
	for (JIndex i=1; i<index; i++)
		{
		JXMenu* aMenu = itsMenus->NthElement(i);
		left += aMenu->GetFrameWidth();
		}

	itsMenus->InsertAtIndex(index, theMenu);

	theMenu->Place(left, bounds.top);
	theMenu->AdjustSize(0, bounds.height() - theMenu->GetFrameHeight());
	MenuWidthChanged(index, theMenu->GetFrameWidth());

	theMenu->SetMenuBar(this);
	theMenu->Show();
}

JBoolean
JXMenuBar::InsertMenuAhead
	(
	JXMenu* existingMenu,
	JXMenu* newMenu
	)
{
	JIndex menuIndex;
	const JBoolean found = itsMenus->Find(existingMenu, &menuIndex);
	if (found)
		{
		InsertMenu(menuIndex, newMenu);
		}
	return found;
}

JBoolean
JXMenuBar::InsertMenuAfter
	(
	JXMenu* existingMenu,
	JXMenu* newMenu
	)
{
	JIndex menuIndex;
	const JBoolean found = itsMenus->Find(existingMenu, &menuIndex);
	if (found)
		{
		InsertMenu(menuIndex+1, newMenu);
		}
	return found;
}

/******************************************************************************
 RemoveMenu

	The caller now owns the menu and is responsible for deleting it.

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

JBoolean
JXMenuBar::RemoveMenu
	(
	JXMenu* theMenu
	)
{
	JIndex menuIndex;
	const JBoolean found = itsMenus->Find(theMenu, &menuIndex);
	if (found)
		{
		RemoveMenu(menuIndex);
		}
	return found;
}

JXMenu*
JXMenuBar::RemoveMenu
	(
	const JIndex index
	)
{
	JXMenu* theMenu = itsMenus->NthElement(index);
	MenuWidthChanged(index, -theMenu->GetFrameWidth());
	itsMenus->RemoveElement(index);
	assert( theMenu->itsMenuBar == this );
	theMenu->itsMenuBar = NULL;		// SetMenuBar() would cause infinite loop
	theMenu->AdjustAppearance();
	theMenu->Hide();
	return theMenu;
}

/******************************************************************************
 DeleteMenu

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

JBoolean
JXMenuBar::DeleteMenu
	(
	JXMenu* theMenu
	)
{
	JIndex menuIndex;
	const JBoolean found = itsMenus->Find(theMenu, &menuIndex);
	if (found)
		{
		DeleteMenu(menuIndex);
		}
	return found;
}

void
JXMenuBar::DeleteMenu
	(
	const JIndex index
	)
{
	JXMenu* theMenu = RemoveMenu(index);
	assert( theMenu->itsOwner == NULL );
	theMenu->itsMenuBar = NULL;
	delete theMenu;
}

/******************************************************************************
 MenuWidthChanged (private)

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

void
JXMenuBar::MenuWidthChanged
	(
	JXMenu*				theMenu,
	const JCoordinate	dw
	)
{
	if (dw != 0)
		{
		JIndex menuIndex;
		const JBoolean found = itsMenus->Find(theMenu, &menuIndex);
		if (found)
			{
			MenuWidthChanged(menuIndex, dw);
			}
		}
}

void
JXMenuBar::MenuWidthChanged
	(
	const JIndex		index,
	const JCoordinate	dw
	)
{
	if (dw != 0)
		{
		const JSize menuCount = itsMenus->GetElementCount();
		for (JIndex i=menuCount; i>index; i--)
			{
			JXMenu* aMenu = itsMenus->NthElement(i);
			aMenu->Move(dw,0);
			}
		}
}

/******************************************************************************
 Draw (virtual protected)

	There is nothing to do since we only act as a container.

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

void
JXMenuBar::Draw
	(
	JXWindowPainter&	p,
	const JRect&		rect
	)
{
}

/******************************************************************************
 DrawBorder (virtual protected)

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

void
JXMenuBar::DrawBorder
	(
	JXWindowPainter&	p,
	const JRect&		frame
	)
{
	JXDrawUpFrame(p, frame, GetBorderWidth());
}
