/******************************************************************************
 JXToolBar.cc

	Implements a user-configurable button toolbar.  The basic idea is that
	one creates a JXToolBar below the JXMenuBar, and places one's own widgets
	inside the JXWidgetSet returned by JXToolBar::GetWidgetEnclosure().
	(This is similar to the way JXScrollbarSet works.)  Since the space
	required by the buttons changes its height when the window's width changes,
	one has to provide the minimum window size (excluding the toolbar's
	height) so the toolbar can call JXWindow::SetMinSize() to keep anything
	from shrinking to zero.

	After creating JXToolBar, one should call LoadPrefs().  If IsEmpty()
	returns kTrue after this, then one should use AppendButton() and NewGroup()
	to set up a default toolbar.  A menu item should be provided to call
	Edit() so the user can change the configuration.

	Every menu item accessible from the given JXMenuBar that has an ID
	will be included in the editor dialog.  If the menu item has an image,
	the "show image" and "show text" checkboxes will control what is displayed
	on the button.  Otherwise, the menu item's text will always be displayed.

	BASE CLASS = public JXWidgetSet

	Copyright © 1998 by Glenn W. Bach.  All rights reserved.

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

#include <JXToolBar.h>
#include <JXToolBarEditDir.h>
#include <JXToolBarNode.h>
#include <JXAdjustToolBarGeometryTask.h>

#include <JTree.h>
#include <JNamedTreeNode.h>

#include <JXFontManager.h>
#include <JXTextMenu.h>
#include <JXTextMenuData.h>
#include <JXImage.h>
#include <JXTimerTask.h>
#include <JXApplication.h>
#include <JXDisplay.h>
#include <JXWindow.h>
#include <JXDirector.h>
#include <JXMenuBar.h>
#include <jXGlobals.h>
#include <jStrStreamUtil.h>
#include <jAssert.h>

const JCoordinate kButtConBuffer 		= 5;
const JCoordinate kLabelBuffer			= 10;

const JSize kTimerDelay					= 1000;

const JSize kSmallButtonHeight			= 24;
const JSize kMedButtonHeight			= 30;

const JCoordinate kCurrentPrefsVersion	= 2;

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

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

JXToolBar::JXToolBar
	(
	JPrefsManager* 		prefsMgr,
	const JPrefID&		id,
	JXMenuBar* 			menuBar,
	const JCoordinate 	minWidth,
	const JCoordinate 	minHeight,
	JXContainer* 		enclosure,
	const HSizingOption hSizing,
	const VSizingOption vSizing,
	const JCoordinate 	x,
	const JCoordinate 	y,
	const JCoordinate 	w,
	const JCoordinate 	h
	)
	:
	JXWidgetSet(enclosure, hSizing, vSizing, x, y, w, h),
	JPrefObject(prefsMgr, id),
	itsNextButtonPosition(kButtConBuffer),
	itsInNewGroupMode(kTrue),
	itsEditDialog(NULL),
	itsMenuTree(NULL),
	itsMenuBar(menuBar),
	itsCurrentButtonHeight(kSmallButtonHeight),
	itsIsShowingButtons(kTrue),
	itsButtonType(JXToolBarButton::kImage),
	itsLoadedPrefs(kFalse),
	itsWindowMinWidth(minWidth),
	itsWindowMinHeight(minHeight)
{
	assert(h >= 40);

	itsButtons = new JPtrArray<JXToolBarButton>;
	assert(itsButtons != NULL);

	itsMenus = new JPtrArray<JXMenu>;
	assert(itsMenus != NULL);

	itsDialogPrefs = new JString;
	assert( itsDialogPrefs != NULL );

	JCoordinate barHeight = itsCurrentButtonHeight + 2* kButtConBuffer;

	itsToolBarSet =
		new JXWidgetSet(this,
			JXWidget::kHElastic, JXWidget::kFixedTop,
			0,0,w, barHeight);
	assert(itsToolBarSet != NULL);

	itsToolBarEnclosure =
		new JXWidgetSet(this,
			JXWidget::kHElastic, JXWidget::kVElastic,
			0,barHeight,w,h - barHeight);
	assert(itsToolBarEnclosure != NULL);

	itsGroupStarts = new JArray<JBoolean>;
	assert(itsGroupStarts != NULL);

	itsTimerTask = new JXTimerTask(kTimerDelay);
	assert(itsTimerTask != NULL);
	JXGetApplication()->InstallIdleTask(itsTimerTask);
	ListenTo(itsTimerTask);

	itsAdjustTask = new JXAdjustToolBarGeometryTask(this);
	assert( itsAdjustTask != NULL );
	JXGetApplication()->InstallUrgentTask(itsAdjustTask);

	ListenTo(prefsMgr);
}

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

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

JXToolBar::~JXToolBar()
{
	delete itsGroupStarts;
	delete itsMenuTree;
	delete itsTimerTask;
	delete itsAdjustTask;
	delete itsButtons;
	delete itsMenus;
	delete itsDialogPrefs;
}

/******************************************************************************
 LoadPrefs (public)

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

void
JXToolBar::LoadPrefs()
{
	JPrefObject::ReadPrefs();
}

/******************************************************************************
 AppendButton

	This should only be called by the client at startup if there are
	no preferences to read in.

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

void
JXToolBar::AppendButton
	(
	JXTextMenu* 	menu,
	const JIndex 	index
	)
{
	itsGroupStarts->AppendElement(itsInNewGroupMode);

	itsInNewGroupMode = kFalse;

	JXToolBarButton* buttcon =
		new JXToolBarButton(menu, index, itsButtonType, itsToolBarSet,
						JXWidget::kFixedLeft, JXWidget::kFixedTop,
						itsNextButtonPosition, kButtConBuffer,
						itsCurrentButtonHeight);
	assert(buttcon != NULL);
	ListenTo(buttcon);
	itsButtons->Append(buttcon);
	itsNextButtonPosition  += buttcon->GetFrameWidth();

	JIndex findex;
	if (!itsMenus->Find(menu, &findex))
		{
		itsMenus->Append(menu);
		}
}

void
JXToolBar::AppendButton
	(
	JXTextMenu* 		menu,
	const JCharacter*	id
	)
{
	JIndex index;
	if (menu->ItemIDToIndex(id, &index))
		{
		AppendButton(menu, index);
		}
}

/******************************************************************************
 NewGroup

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

void
JXToolBar::NewGroup()
{
	if (itsInNewGroupMode)
		{
		return;
		}
	itsNextButtonPosition  += kButtConBuffer;
	itsInNewGroupMode		= kTrue;
}

/******************************************************************************
 Receive

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

void
JXToolBar::Receive
	(
	JBroadcaster* 	sender,
	const Message&	message
	)
{
	JBoolean propagate = kTrue;

	if (message.Is(JXButton::kPushed))
		{
		const JSize count = itsButtons->GetElementCount();
		for (JSize i = 1; i <= count; i++)
			{
			JXToolBarButton* button = itsButtons->NthElement(i);
			if (sender == button)
				{
				JXTextMenu* menu = button->GetMenu();
				menu->PrepareToOpenMenu();
				if (menu->itsBaseItemData->IsEnabled(button->GetMenuItem()))
					{
					JXDisplay* display = GetDisplay();	// need local copy, since we might be deleted
					Display* xDisplay  = *display;
					Window xWindow     = (GetWindow())->GetXWindow();

					menu->BroadcastSelection(button->GetMenuItem());

					if (!JXDisplay::WindowExists(display, xDisplay, xWindow))
						{
						// we have been deleted
						return;
						}

					UpdateButtons();
					}
				propagate = kFalse;
				break;
				}
			}
		}
	else if (sender == itsTimerTask && message.Is(JXTimerTask::kTimerWentOff))
		{
		UpdateButtons();
		propagate = kFalse;
		}
	else if (sender == itsEditDialog && message.Is(JXDialogDirector::kDeactivated))
		{
		JXDialogDirector::Deactivated* info =
			dynamic_cast(JXDialogDirector::Deactivated*, &message);
		assert(info != NULL);
		if (info->Successful())
			{
			ExtractChanges();
			}
		delete itsMenuTree;
		itsMenuTree = NULL;
		itsEditDialog = NULL;
		propagate = kFalse;
		}
	else if ((sender == GetPrefsManager()) && message.Is(JPrefsManager::kDataChanged))
		{
		JPrefsManager::DataChanged* info =
			dynamic_cast(JPrefsManager::DataChanged*, &message);
		assert(info != NULL);
		if (info->GetID() == GetID())
			{
			JPrefObject::ReadPrefs();
			}
		propagate = kFalse;
		}

	// If nobody else handled it, pass it to the base class.

	if (propagate)
		{
		JXWidgetSet::Receive(sender, message);
		}
}

/******************************************************************************
 Edit (public)

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

void
JXToolBar::Edit()
{
	assert(itsEditDialog == NULL);

	BuildTree();

	JBoolean small = JI2B(itsCurrentButtonHeight == kSmallButtonHeight);

	itsEditDialog =
		new JXToolBarEditDir(itsMenuTree, itsIsShowingButtons,
							 small, itsButtonType,
							 this->GetWindow()->GetDirector());
	assert(itsEditDialog != NULL);

	if (!itsDialogPrefs->IsEmpty())
		{
		jistrstream(is, itsDialogPrefs->GetCString(), itsDialogPrefs->GetLength());
		itsEditDialog->ReadSetup(is);
		}
	itsEditDialog->BeginDialog();
	ListenTo(itsEditDialog);
}

/******************************************************************************
 ExtractChanges (private)

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

void
JXToolBar::ExtractChanges()
{
	itsButtons->DeleteAll();
	itsGroupStarts->RemoveAll();

	SetButtonType(itsEditDialog->GetType());
	UseSmallButtons(itsEditDialog->UseSmallButtons());

	itsInNewGroupMode 		= kTrue;
	itsNextButtonPosition	= kButtConBuffer;
	JTreeNode* base = itsMenuTree->GetRoot();
	JSize menuCount = base->GetChildCount();
	for (JSize i = 1; i <= menuCount; i++)
		{
		JTreeNode* node = base->GetChild(i);
		ExtractItemNodes(node);
		}

	AdjustToolBarGeometry();
	ShowToolBar(itsEditDialog->ShowToolBar());

	ostrstream data;
	itsEditDialog->WriteSetup(data);
	*itsDialogPrefs = data.str();
	JUnfreeze(data);

	JPrefObject::WritePrefs();
}

/******************************************************************************
 ExtractItemNodes (public)

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

void
JXToolBar::ExtractItemNodes
	(
	JTreeNode* menuNode
	)
{
	JSize itemCount = menuNode->GetChildCount();
	NewGroup();
	for (JSize j = 1; j <= itemCount; j++)
		{
		JTreeNode* child 	= menuNode->GetChild(j);
		if (child->IsOpenable())
			{
			ExtractItemNodes(child);
			NewGroup();
			}
		else
			{
			JXToolBarNode* item	= dynamic_cast(JXToolBarNode*, child);
			assert(item != NULL);
			if (item->IsChecked())
				{
				AppendButton(item->GetMenu(), item->GetIndex());
				}
			if (item->HasSeparator())
				{
				NewGroup();
				}
			}
		}
}

/******************************************************************************
 BuildTree (private)

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

void
JXToolBar::BuildTree()
{
	assert(itsMenuTree == NULL);
	JNamedTreeNode* base = new JNamedTreeNode(NULL, "BASE");
	assert(base != NULL);
	itsMenuTree = new JTree(base);
	assert(itsMenuTree != NULL);

	JSize count = itsMenuBar->GetMenuCount();
	for (JSize i = 1; i <= count; i++)
		{
		JXMenu* menu 		= itsMenuBar->GetMenu(i);
		JXTextMenu* tmenu	= dynamic_cast(JXTextMenu*, menu);
		assert(tmenu != NULL);
		AddMenuToTree(tmenu, base, tmenu->GetTitle());
		}
}

/******************************************************************************
 AddMenuToTree (private)

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

void
JXToolBar::AddMenuToTree
	(
	JXTextMenu* 		menu,
	JNamedTreeNode* 	parent,
	const JCharacter*	name
	)
{
	JNamedTreeNode* mnode = new JNamedTreeNode(parent->GetTree(), name);
	assert(mnode != NULL);
	parent->Append(mnode);
	JSize itemCount = menu->GetItemCount();
	for (JSize j = 1; j <= itemCount; j++)
		{
		JString name 		= menu->GetItemText(j);
		const JXMenu* sub;
		if (menu->GetSubmenu(j, &sub))
			{
			const JXTextMenu* temp	= dynamic_cast(const JXTextMenu*, sub);
			JXTextMenu* tsub = const_cast<JXTextMenu*>(temp);
			AddMenuToTree(tsub, mnode, name);
			}
		else
			{
			JBoolean separator	= menu->HasSeparatorAfter(j);
			JBoolean checked	= ItemIsUsed(menu, j);

			const JString* id;
			if (menu->GetItemID(j, &id))
				{
				JXToolBarNode* tbnode =
					new JXToolBarNode(menu, j, separator, checked, itsMenuTree, mnode, name);
				assert(tbnode != NULL);
				}
			}
		}
	if (mnode->GetChildCount() == 0)
		{
		delete mnode;
		}
}

/******************************************************************************
 ItemIsUsed (private)

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

JBoolean
JXToolBar::ItemIsUsed
	(
	JXTextMenu*		menu,
	const JIndex	index
	)
{
	JSize count = itsButtons->GetElementCount();
	for (JSize i = 1; i <= count; i++)
		{
		JXToolBarButton* button = itsButtons->NthElement(i);
		if ((button->GetMenu() 		== menu) &&
			(button->GetMenuItem() 	== index))
			{
			return kTrue;
			}
		}
	return kFalse;
}

/******************************************************************************
 ReadPrefs (public)

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

void
JXToolBar::ReadPrefs
	(
	istream& is
	)
{
	itsLoadedPrefs = kTrue;
	itsButtons->DeleteAll();
	itsGroupStarts->RemoveAll();
	JCoordinate version;
	is >> version;

	JBoolean show;
	is >> show;
	ShowToolBar(show);
	JBoolean useSmall;
	is >> useSmall;
	UseSmallButtons(useSmall);
	if (version == 1)
		{
		JBoolean textOnly;
		is >> textOnly;
		if (textOnly)
			{
			SetButtonType(JXToolBarButton::kText);
			}
		}
	else
		{
		JIndex type;
		is >> type;
		SetButtonType((JXToolBarButton::Type)type);
		}

	JSize count;
	is >> count;

	for (JIndex i = 1; i <= count; i++)
		{
		JString id;
		is >> id;
		JBoolean group;
		is >> group;
		if (!id.IsEmpty())
			{
			if (group)
				{
				NewGroup();
				}
			FindItemAndAdd(id);
			}
		}

	is >> *itsDialogPrefs;

	AdjustToolBarGeometry();
}

/******************************************************************************
 WritePrefs (public)

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

void
JXToolBar::WritePrefs
	(
	ostream& os
	)
	const
{
	os << kCurrentPrefsVersion;
	os << ' ' << itsIsShowingButtons;
	os << ' ' << JI2B(itsCurrentButtonHeight == kSmallButtonHeight);
	os << ' ' << (JIndex) itsButtonType;

	const JSize count = itsButtons->GetElementCount();
	os << ' ' << count;

	for (JIndex i = 1; i <= count; i++)
		{
		JXToolBarButton* button = itsButtons->NthElement(i);
		JXTextMenu* menu 		= button->GetMenu();
		JIndex index			= button->GetMenuItem();
		JBoolean group			= itsGroupStarts->GetElement(i);
		const JString* id;
		menu->GetItemID(index, &id);
		os << ' ' << *id;
		os << ' ' << group;
		}

	os << ' ' << *itsDialogPrefs;
}

/******************************************************************************
 FindItemAndAdd (private)

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

void
JXToolBar::FindItemAndAdd
	(
	const JString& id
	)
{
	JSize count = itsMenuBar->GetMenuCount();
	for (JSize i = 1; i <= count; i++)
		{
		JXMenu* menu 		= itsMenuBar->GetMenu(i);
		JXTextMenu* tmenu	= dynamic_cast(JXTextMenu*, menu);
		assert(tmenu != NULL);
		FindItemAndAdd(tmenu, id);
		}
}

void
JXToolBar::FindItemAndAdd
	(
	JXTextMenu* 	menu,
	const JString& 	id
	)
{
	JSize count = menu->GetItemCount();
	for (JSize i = 1; i <= count; i++)
		{
		const JXMenu* sub;
		if (menu->GetSubmenu(i, &sub))
			{
			const JXTextMenu* temp	= dynamic_cast(const JXTextMenu*, sub);
			JXTextMenu* tsub = const_cast<JXTextMenu*>(temp);
			FindItemAndAdd(tsub, id);
			}
		else
			{
			const JString* testID;
			if (menu->GetItemID(i, &testID))
				{
				if (*testID == id)
					{
					AppendButton(menu, i);
					return;
					}
				}
			}
		}
}

/******************************************************************************
 IsEmpty (public)

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

JBoolean
JXToolBar::IsEmpty()
	const
{
	return itsButtons->IsEmpty();
}

/******************************************************************************
 AdjustGeometryIfNeeded (private)

	Called by JXAdjustToolBarGeometryTask.

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

void
JXToolBar::AdjustGeometryIfNeeded()
{
	if (!itsLoadedPrefs)
		{
		AdjustToolBarGeometry();
		}
}

/******************************************************************************
 AdjustToolBarGeometry (public)

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

void
JXToolBar::AdjustToolBarGeometry()
{
	if (itsIsShowingButtons)
		{
		RevertBar();

		itsNextButtonPosition 	= kButtConBuffer;
		itsCurrentLineY			= kButtConBuffer;
		JArray<JIndexRange> groups;
		GetGroups(&groups);
		JSize count = groups.GetElementCount();
		for (JSize i = 1; i <= count; i++)
			{
			JIndexRange range = groups.GetElement(i);
			PlaceGroup(range);
			}

		AdjustWindowMinSize();

		itsToolBarEnclosure->Place(0,itsToolBarSet->GetBoundsHeight());
		itsToolBarEnclosure->SetSize(GetBoundsWidth(), GetBoundsHeight() - itsToolBarSet->GetBoundsHeight());
		}
}

/******************************************************************************
 GetGroups (private)

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

void
JXToolBar::GetGroups
	(
	JArray<JIndexRange>* groups
	)
{
	if (IsEmpty())
		{
		return;
		}
	JIndexRange range;
	range.first = 1;
	JSize count = itsButtons->GetElementCount();
	for (JSize i = 2; i <= count; i++)
		{
		if (itsGroupStarts->GetElement(i))
			{
			range.last = i - 1;
			groups->AppendElement(range);
			range.first = i;
			}
		}
	range.last = count;
	groups->AppendElement(range);
}

/******************************************************************************
 PlaceGroup (private)

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

void
JXToolBar::PlaceGroup
	(
	const JIndexRange& range
	)
{
	JCoordinate groupWidth = GetGroupWidth(range);
	if (groupWidth <= GetBoundsWidth())
		{
		JCoordinate groupEnd = itsNextButtonPosition + groupWidth;
		if (groupEnd > GetBoundsWidth())
			{
			NewLine();
			}
		for (JSize i = range.first; i <= range.last; i++)
			{
			PlaceButton(i);
			}
		}
	else
		{
		for (JSize i = range.first; i <= range.last; i++)
			{
			JXToolBarButton* button = itsButtons->NthElement(i);
			JCoordinate butWidth 	= button->GetFrameWidth();
			JCoordinate totalWidth	= GetBoundsWidth();
			if (itsNextButtonPosition + butWidth <= totalWidth)
				{
				PlaceButton(i);
				}
			else if (butWidth > totalWidth)
				{
				if (itsNextButtonPosition != kButtConBuffer)
					{
					NewLine();
					}
				PlaceButton(i);
				}
			else
				{
				NewLine();
				PlaceButton(i);
				}
			}
		}
	itsNextButtonPosition += kButtConBuffer;
}

/******************************************************************************
 PlaceButton (private)

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

void
JXToolBar::PlaceButton
	(
	const JIndex index
	)
{
	JXToolBarButton* button = itsButtons->NthElement(index);
	button->Place(itsNextButtonPosition, itsCurrentLineY);
	itsNextButtonPosition += button->GetFrameWidth();
}

/******************************************************************************
 GetGroupWidth (private)

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

JSize
JXToolBar::GetGroupWidth
	(
	const JIndexRange& range
	)
{
	JSize w = 0;
	for (JSize index = range.first; index <= range.last; index++)
		{
		JXToolBarButton* button = itsButtons->NthElement(index);
		w += button->GetFrameWidth();
		}
	return w;
}

/******************************************************************************
 RevertBar (private)

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

void
JXToolBar::RevertBar()
{
	const JCoordinate delta = itsToolBarSet->GetBoundsHeight()
							  - itsCurrentButtonHeight - 2*kButtConBuffer;
	itsToolBarSet->AdjustSize(0, -delta);
//	itsToolBarEnclosure->Move(0, -delta);
//	itsToolBarEnclosure->AdjustSize(0, delta);
}

/******************************************************************************
 NewLine (private)

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

void
JXToolBar::NewLine()
{
	itsNextButtonPosition 	= kButtConBuffer;
	const JCoordinate delta = kButtConBuffer + itsCurrentButtonHeight;
	itsCurrentLineY			= itsCurrentLineY + delta;
	itsToolBarSet->AdjustSize(0, delta);
//	itsToolBarEnclosure->Move(0, delta);
//	itsToolBarEnclosure->AdjustSize(0, -delta);
}

/******************************************************************************
 UseSmallButtons (public)

 	This should only be called by the client at startup if there are
	no preferences to read in. It should be called before adding any
	buttons.

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

void
JXToolBar::UseSmallButtons
	(
	const JBoolean useSmall
	)
{
	if (useSmall)
		{
		itsCurrentButtonHeight = kSmallButtonHeight;
		}
	else
		{
		itsCurrentButtonHeight = kMedButtonHeight;
		}
}

JBoolean
JXToolBar::IsUsingSmallButtons()
	const
{
	return JI2B(itsCurrentButtonHeight == kSmallButtonHeight);
}

/******************************************************************************
 ShowToolBar (public)

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

void
JXToolBar::ShowToolBar
	(
	const JBoolean show
	)
{
	if (show && !itsIsShowingButtons)
		{
		itsToolBarSet->Show();
		itsIsShowingButtons = kTrue;
		AdjustWindowMinSize();

		itsToolBarEnclosure->Place(0,itsToolBarSet->GetBoundsHeight());
		itsToolBarEnclosure->SetSize(GetBoundsWidth(), GetBoundsHeight() - itsToolBarSet->GetBoundsHeight());

		(JXGetApplication())->InstallIdleTask(itsTimerTask);
		}
	else if (!show && itsIsShowingButtons)
		{
		itsToolBarSet->Hide();
		itsIsShowingButtons = kFalse;
		AdjustWindowMinSize();

		itsToolBarEnclosure->Place(0,0);
		itsToolBarEnclosure->SetSize(GetBoundsWidth(), GetBoundsHeight());

		(JXGetApplication())->RemoveIdleTask(itsTimerTask);
		}
}

/******************************************************************************
 ApertureResized (protected)

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

void
JXToolBar::ApertureResized
	(
	const JCoordinate dw,
	const JCoordinate dh
	)
{
	JXWidgetSet::ApertureResized(dw, dh);
	AdjustToolBarGeometry();
}

/******************************************************************************
 SetButtonType (public)

	Must be called before adding any buttons.

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

void
JXToolBar::SetButtonType
	(
	const JXToolBarButton::Type type
	)
{
	itsButtonType = type;
}

JXToolBarButton::Type
JXToolBar::GetButtonType()
	const
{
	return itsButtonType;
}

/******************************************************************************
 UpdateButtons (private)

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

void
JXToolBar::UpdateButtons()
{
JIndex i;

	const JSize count = itsMenus->GetElementCount();
	for (i = 1; i <= count; i++)
		{
		JXMenu* menu = itsMenus->NthElement(i);
		menu->PrepareToOpenMenu();
		}
	JBoolean needsAdjustment = kFalse;
	const JSize bcount = itsButtons->GetElementCount();
	for (i = 1; i <= bcount; i++)
		{
		JXToolBarButton* button = itsButtons->NthElement(i);
		if (button->GetMenu()->itsBaseItemData->IsEnabled(button->GetMenuItem()))
			{
			button->Activate();
			}
		else
			{
			button->Deactivate();
			}
		if (button->NeedsGeometryAdjustment())
			{
			needsAdjustment = kTrue;
			}
		button->Refresh();
		}
	if (needsAdjustment)
		{
		AdjustToolBarGeometry();
		}
}

/******************************************************************************
 AdjustWindowMinSize (private)

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

void
JXToolBar::AdjustWindowMinSize()
{
	JCoordinate minHeight = itsWindowMinHeight;
	if (itsIsShowingButtons)
		{
		minHeight += itsToolBarSet->GetFrameHeight();
		}
	GetWindow()->SetMinSize(itsWindowMinWidth, minHeight);
}

#define JTemplateType JXToolBarButton
#include <JPtrArray.tmpls>
#undef JTemplateType
