void
JXTreeListWidget::AdjustColWidths()
{
	if (itsAdjustToTreeTask != NULL)
		{
		return;
		}

	const JSize colCount = GetColCount();
	if (itsMinColWidths->GetElementCount() != colCount)
		{
		NeedsAdjustToTree();
		return;
		}

	for (JIndex i=1; i<=colCount; i++)
		{
		SetColWidth(i, itsMinColWidths->GetElement(i));
		}

	if (ColIndexValid(itsElasticColIndex))
		{
		const JCoordinate minReqWidth = itsMinColWidths->GetElement(itsElasticColIndex);
		if (minReqWidth > 0)
			{
			const JCoordinate availWidth =
				GetApertureWidth() - (GetBoundsWidth() - GetColWidth(itsElasticColIndex));
			SetColWidth(itsElasticColIndex, JMax(minReqWidth, availWidth));
			}
		}
}
JXTreeListWidget::JXTreeListWidget
	(
	JTreeList*			treeList,
	JXScrollbarSet*		scrollbarSet,
	JXContainer*		enclosure,
	const HSizingOption	hSizing,
	const VSizingOption	vSizing,
	const JCoordinate	x,
	const JCoordinate	y,
	const JCoordinate	w,
	const JCoordinate	h
	)
	:
	JXStyleTable(scrollbarSet, enclosure, hSizing,vSizing, x,y, w,h),
	itsToggleOpenColIndex(0),
	itsNodeColIndex(0),
	itsElasticColIndex(0)
{
	itsTreeList = treeList;
	ListenTo(itsTreeList);

	itsMinColWidths = new JArray<JSize>;
	assert( itsMinColWidths != NULL );

	itsReselectNodeList = new JPtrArray<JTreeNode>(JPtrArrayT::kForgetAll);
	assert( itsReselectNodeList != NULL );
	ListenTo(itsTreeList->GetTree());

	itsIndentWidth       = kDefaultIndent;
	itsDrawSelectionFlag = kJTrue;
	itsAdjustToTreeTask  = NULL;
	itsToggleDragIndex   = 0;
	itsDNDTargetIndex    = 0;
	itsMaxOpenDepth      = kDefaultMaxOpenDepth;
	itsSavedScrollSetup  = NULL;

	SetRowBorderInfo(0, GetBackColor());
	SetColBorderInfo(0, GetBackColor());

	ShouldActLike1DList();

	NeedsAdjustToTree();

	AppendRows(itsTreeList->GetElementCount());
	AppendCols(2, kToggleColWidth);		// second width adjusts automatically

	itsToggleOpenColIndex = 1;
	itsNodeColIndex       = 2;
	itsElasticColIndex    = itsNodeColIndex;
	ListenTo(this);
}
void
JXTreeListWidget::Receive
	(
	JBroadcaster*	sender,
	const Message&	message
	)
{
	if (sender == itsTreeList && message.Is(JTreeList::kNodeInserted))
		{
		const JTreeList::NodeInserted* info =
			dynamic_cast(const JTreeList::NodeInserted*, &message);
		assert( info != NULL );
		InsertRows(info->GetIndex(), 1);
		NeedsAdjustToTree();
		}

	else if (sender == itsTreeList && message.Is(JTreeList::kNodeRemoved))
void
JXTreeListWidget::Receive
	(
	JBroadcaster*	sender,
	const Message&	message
	)
{
	if (sender == itsTreeList && message.Is(JTreeList::kNodeInserted))
		{
		const JTreeList::NodeInserted* info =
			dynamic_cast<const JTreeList::NodeInserted*>(&message);
		assert( info != NULL );
		InsertRows(info->GetIndex(), 1);
		NeedsAdjustToTree();
		}

	else if (sender == itsTreeList && message.Is(JTreeList::kNodeRemoved))
		{
		const JTreeList::NodeRemoved* info =
			dynamic_cast<const JTreeList::NodeRemoved*>(&message);
		assert( info != NULL );
		RemoveRow(info->GetIndex());
		NeedsAdjustToTree();
		}

	else if (sender == itsTreeList && message.Is(JTreeList::kNodeChanged))
		{
		const JTreeList::NodeChanged* info =
			dynamic_cast<const JTreeList::NodeChanged*>(&message);
		assert( info != NULL );
		TableRefreshRow(info->GetIndex());
		NeedsAdjustToTree();
		}

	else if (sender == itsTreeList &&
			 (message.Is(JTreeList::kNodeOpened) ||
			  message.Is(JTreeList::kNodeClosed)))
		{
		const JTreeList::NodeMessage* info =
			dynamic_cast<const JTreeList::NodeMessage*>(&message);
		assert( info != NULL );
		TableRefreshRow(info->GetIndex());
		}

	else if (sender == itsTreeList->GetTree() &&
			 message.Is(JTree::kPrepareForNodeMove))
		{
		HandlePrepareForNodeMove();
		}

	else if (sender == itsTreeList->GetTree() &&
			 message.Is(JTree::kNodeMoveFinished))
		{
		HandleNodeMoveFinished();
		}

	else
		{
		if (sender == this && message.Is(kColsInserted))
			{
			const ColsInserted* info = dynamic_cast<const ColsInserted*>(&message);
			assert( info != NULL );
			info->AdjustIndex(&itsToggleOpenColIndex);
			info->AdjustIndex(&itsNodeColIndex);
			info->AdjustIndex(&itsElasticColIndex);
			NeedsAdjustToTree();
			}

		else if (sender == this && message.Is(kColsRemoved))
			{
			const ColsRemoved* info = dynamic_cast<const ColsRemoved*>(&message);
			assert( info != NULL );
			JBoolean ok = info->AdjustIndex(&itsToggleOpenColIndex);
			assert( ok );
			ok = info->AdjustIndex(&itsNodeColIndex);
			assert( ok );
			info->AdjustIndex(&itsElasticColIndex);		// ok to let it go to zero
			NeedsAdjustToTree();
			}

		else if (sender == this && message.Is(kColMoved))
			{
			const ColMoved* info =
				dynamic_cast<const ColMoved*>(&message);
			assert( info != NULL );
			info->AdjustIndex(&itsToggleOpenColIndex);
			info->AdjustIndex(&itsNodeColIndex);
			info->AdjustIndex(&itsElasticColIndex);
			itsMinColWidths->MoveElementToIndex(info->GetOrigIndex(), info->GetNewIndex());
			}

		JXStyleTable::Receive(sender, message);
		}
}