/******************************************************************************
 JXCurveNameList.cc

	BASE CLASS = public JXEditTable

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

#include <JXCurveNameList.h>

#include <JXColormap.h>
#include <JXInputField.h>

#include <JFontManager.h>
#include <JPainter.h>
#include <JTableSelection.h>

#include <jGlobals.h>
#include <jASCIIConstants.h>

#include <jAssert.h>

const JCoordinate kHMarginWidth = 3;
const JCoordinate kVMarginWidth = 1;
const JCoordinate kDefColWidth  = 100;

const JCharacter* JXCurveNameList::kNameSelected    = "JXCurveNameList::kNameSelected";

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

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

JXCurveNameList::JXCurveNameList
	(
	JXScrollbarSet*		scrollbarSet,
	JXContainer*		enclosure,
	const HSizingOption	hSizing,
	const VSizingOption	vSizing,
	const JCoordinate	x,
	const JCoordinate	y,
	const JCoordinate	w,
	const JCoordinate	h
	)
	:
   JXEditTable(1, kDefColWidth, scrollbarSet, enclosure, hSizing,vSizing, x,y, w,h),
   itsInput(NULL)
{
	itsNameList = new JPtrArray<JString>;
	assert(itsNameList != NULL);
	ListenTo(itsNameList);

	itsMinColWidth = 1;

	JXColormap* colormap         = GetColormap();
	const JColorIndex blackColor = colormap->GetBlackColor();
	SetRowBorderInfo(0, blackColor);
	SetColBorderInfo(0, blackColor);

	const JSize fontHeight =
		(GetFontManager())->GetLineHeight(JGetDefaultFontName(), 
		kJXDefaultFontSize, JFontStyle());
	const JCoordinate rowHeight = fontHeight + 2*kVMarginWidth;
	SetDefaultRowHeight(rowHeight);
	SetAllRowHeights(rowHeight);

	AppendCol();
}

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

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

JXCurveNameList::~JXCurveNameList()
{
	delete itsNameList;	// we don't own the strings
}

/******************************************************************************
 HandleMouseDown (protected)

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

void
JXCurveNameList::HandleMouseDown
	(
	const JPoint& 			pt,
	const JXMouseButton 	button,
	const JSize 			clickCount,
	const JXButtonStates&	buttonStates,
	const JXKeyModifiers&	modifiers
	)
{
	JPoint cell;
	if (button == kJXLeftButton && clickCount == 1 &&
		GetCell(pt, &cell))
		{
		JTableSelection& s = GetTableSelection();
		if (!s.IsSelected(cell))
			{
			s.ClearSelection();
			s.SelectRow(cell.y);
			Broadcast(NameSelected(cell.y));
			}
		BeginEditing(cell);
		}
	else
		{
		ScrollForWheel(button, modifiers);
		}
}

/******************************************************************************
 AppendName (public)

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

void
JXCurveNameList::AppendName
	(
	JString* name
	)
{
	itsNameList->Append(name);
}	
/******************************************************************************
 SetCurrentName (public)

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

void
JXCurveNameList::SetCurrentName
	(
	const JIndex index
	)
{
	assert(index <= itsNameList->GetElementCount());
	JTableSelection& s = GetTableSelection();
	s.ClearSelection();
	s.SelectRow(index);
}

/******************************************************************************
 TableDrawCell (virtual protected)

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

void
JXCurveNameList::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	HilightIfSelected(p, cell, rect);

	p.SetFont(JGetDefaultFontName(), kJXDefaultFontSize, JFontStyle());

	const JString* str = itsNameList->NthElement(cell.y);

	// check that column is wide enough

	const JCoordinate w = p.GetStringWidth(*str) + 2*kHMarginWidth;
	if (w > GetColWidth(1))
		{
		itsMinColWidth = w;
		}

	// draw string

	JRect r = rect;
	r.left += kHMarginWidth;
	p.String(r, *str, JPainter::kHAlignLeft, JPainter::kVAlignCenter);
	if (cell.y == JCoordinate(itsNameList->GetElementCount()))
		{
		AdjustColWidth();
		}
}

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

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

void
JXCurveNameList::ApertureResized
	(
	const JCoordinate dw,
	const JCoordinate dh
	)
{
	JXTable::ApertureResized(dw,dh);
	AdjustColWidth();
}

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

	Listen for changes in our list.

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

void
JXCurveNameList::Receive
	(
	JBroadcaster*	sender,
	const Message&	message
	)
{
	if (sender == const_cast<JPtrArray<JString>*>(itsNameList) &&
		message.Is(JOrderedSetT::kElementsInserted))
		{
		const JOrderedSetT::ElementsInserted* info =
			dynamic_cast(const JOrderedSetT::ElementsInserted*, &message);
		assert( info != NULL );
		const JIndex firstIndex = info->GetFirstIndex();
		const JSize count       = info->GetCount();
		for (JIndex i=1; i<=count; i++)
			{
			InsertRow(firstIndex);
			}
		}

	else if (sender == const_cast<JPtrArray<JString>*>(itsNameList) &&
			 message.Is(JOrderedSetT::kElementsRemoved))
		{
		const JOrderedSetT::ElementsRemoved* info =
			dynamic_cast(const JOrderedSetT::ElementsRemoved*, &message);
		assert( info != NULL );
		const JIndex firstIndex = info->GetFirstIndex();
		const JSize count       = info->GetCount();
		itsMinColWidth = 1;
		for (JIndex i=1; i<=count; i++)
			{
			RemoveRow(firstIndex);
			}
		}

	else if (sender == const_cast<JPtrArray<JString>*>(itsNameList) &&
			 message.Is(JOrderedSetT::kAllElementsRemoved))
		{
		itsMinColWidth = 1;
		RemoveAllRows();
		}

	else if (sender == const_cast<JPtrArray<JString>*>(itsNameList) &&
			 message.Is(JOrderedSetT::kElementMoved))
		{
		const JOrderedSetT::ElementMoved* info =
			dynamic_cast(const JOrderedSetT::ElementMoved*, &message);
		assert( info != NULL );
		const JIndex origIndex = info->GetOrigIndex();
		const JIndex newIndex  = info->GetNewIndex();
		MoveRow(origIndex, newIndex);
		}

	else if (sender == const_cast<JPtrArray<JString>*>(itsNameList) &&
			 message.Is(JOrderedSetT::kElementsSwapped))
		{
		const JOrderedSetT::ElementsSwapped* info =
			dynamic_cast(const JOrderedSetT::ElementsSwapped*, &message);
		assert( info != NULL );
		const JIndex index1 = info->GetIndex1();
		const JIndex index2 = info->GetIndex2();
		}

	else if (sender == const_cast<JPtrArray<JString>*>(itsNameList) &&
			 message.Is(JOrderedSetT::kSorted))
		{
		assert( 0 );	// we don't allow this
		}

	else if (sender == const_cast<JPtrArray<JString>*>(itsNameList) &&
			 message.Is(JOrderedSetT::kElementChanged))
		{
		itsMinColWidth = 1;
		Refresh();
		}

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

/******************************************************************************
 AdjustColWidth (private)

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

void
JXCurveNameList::AdjustColWidth()
{
	JCoordinate w = GetApertureWidth();
	if (w < itsMinColWidth)
		{
		w = itsMinColWidth;
		}
	SetColWidth(1,w);
}

/******************************************************************************
 CreateXInputField (virtual protected)

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

JXInputField*
JXCurveNameList::CreateXInputField
	(
	const JPoint& 		cell,
	const JCoordinate 	x, 
	const JCoordinate 	y,
	const JCoordinate 	w, 
	const JCoordinate 	h
	)
{
	assert(itsInput == NULL);
	itsInput = 
		new JXInputField(this, 
				JXWidget::kHElastic, JXWidget::kVElastic,
				x, y, w, h);
	assert(itsInput != NULL);
	assert(cell.y <= (JCoordinate)(itsNameList->GetElementCount()));
	itsInput->SetText(*(itsNameList->NthElement(cell.y)));
	return itsInput;
}

/******************************************************************************
 DeleteXInputField (virtual protected)

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

void
JXCurveNameList::DeleteXInputField()
{
	delete itsInput;
	itsInput = NULL;
}

/******************************************************************************
 ExtractInputData (virtual protected)

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

JBoolean
JXCurveNameList::ExtractInputData
	(
	const JPoint& cell
	)
{
	JString name = itsInput->GetText();
	if (name.IsEmpty())
		{
		return kFalse;
		}
	assert(cell.y <= (JCoordinate)(itsNameList->GetElementCount()));
	*(itsNameList->NthElement(cell.y)) = name;
	return kTrue;
}

/******************************************************************************
 HandleKeyPress (virtual public)

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

void
JXCurveNameList::HandleKeyPress
	(
	const int 				key,
	const JXKeyModifiers&	modifiers
	)
{
	if (key == kJEscapeKey)
		{
		if (IsEditing())
			{
			CancelEditing();
			}
		}
	else if (key == kJReturnKey)
		{
		if (IsEditing())
			{
			EndEditing();
			}
		}
	else
		{
		JXTable::HandleKeyPress(key, modifiers);
		}
}
