//
//	Copyright © 2006 Nemetschek North America 
//	All Rights Reserved.
//
// Created by Vladislav Stanev

#include "StdHeaders.h"

#include "ListBrowserCtrl.h"
#include "ListBrowserColumn.h"
#include "ListBrowserItem.h"

#include "Dialog.h"

using namespace VectorWorks::VWUI;

VWListBrowserCtrl::VWListBrowserCtrl(TControlID id)
: VWControl( id )
{
}

VWListBrowserCtrl::~VWListBrowserCtrl()
{
}

bool VWListBrowserCtrl::CreateControl(VWDialog* pDlg, short widthInCharacters, short heightInLines)
{
	farrIndexToMarker.clear();
	::GS_CreateListBrowser( gCBP, pDlg->GetControlID(), fControlID, widthInCharacters, heightInLines );
	return VWControl::CreateControl( pDlg );
}

void VWListBrowserCtrl::EnableControl(bool enable)
{
	VERIFYN( kVStanev, ::GS_EnableListBrowser( gCBP, fpParentDlg->GetControlID(), fControlID, enable ) );
}

void VWListBrowserCtrl::EnableClickAllDataChange(bool enable)
{
	VERIFYN( kVStanev, ::GS_EnableListBrowserClickAllDataChange( gCBP, fpParentDlg->GetControlID(), fControlID, enable ) );
}

void VWListBrowserCtrl::EnableDragAndDrop(bool enable)
{
	VERIFYN( kVStanev, ::GS_EnableListBrowserDragAndDrop( gCBP, fpParentDlg->GetControlID(), fControlID, enable) );
}

void VWListBrowserCtrl::SetFocusOnControl()
{
	VERIFYN( kVStanev, ::GS_SetFocusOnListBrowser( gCBP, fpParentDlg->GetControlID(), fControlID ) );
}

void VWListBrowserCtrl::RefreshControl()
{
	VERIFYN( kVStanev, ::GS_RefreshListBrowser( gCBP, fpParentDlg->GetControlID(), fControlID ) );
}

bool VWListBrowserCtrl::IsSortingEnabled() const
{
	return ::GS_IsListBrowserSortingEnabled( gCBP, fpParentDlg->GetControlID(), fControlID ) ? true : false;
}

void VWListBrowserCtrl::EnableSorting(bool enable)
{
	::GS_EnableListBrowserSorting( gCBP, fpParentDlg->GetControlID(), fControlID, enable );
}

size_t VWListBrowserCtrl::GetSelectedItemsCount()
{
	return (size_t) ::GS_GetNumSelectedListBrowserItems( gCBP, fpParentDlg->GetControlID(), fControlID );
}

void VWListBrowserCtrl::EnableSingleLineSelection(bool enable)
{
	VERIFYN( kVStanev, ::GS_EnableListBrowserSingleLineSelection( gCBP, fpParentDlg->GetControlID(), fControlID, enable ) );
}

void VWListBrowserCtrl::EnableUpdates(bool enable)
{
	VERIFYN( kVStanev, ::GS_EnableListBrowserUpdates( gCBP, fpParentDlg->GetControlID(), fControlID, enable ) );
}

void VWListBrowserCtrl::SelectRow(size_t rowIndex, bool select) const
{
	this->SelectRow( rowIndex, rowIndex, select );
}

void VWListBrowserCtrl::SelectRow(size_t firstRowIndex, size_t lastRowIndex, bool select) const
{
	VERIFYN( kVStanev, ::GS_SetListBrowserSelection( gCBP, fpParentDlg->GetControlID(), fControlID, DemoteTo<short> ( kVStanev, firstRowIndex ), DemoteTo<short> ( kVStanev, lastRowIndex ), select ) );
}

void VWListBrowserCtrl::DeselectAll() const
{
	size_t	rowIndex	= this->GetFirstSelected();
	if ( rowIndex != size_t(-1) ) {
		do
		{
			this->SelectRow( rowIndex, rowIndex, false );
		} while( this->GetNextSelected( rowIndex ) );
	}
}

long VWListBrowserCtrl::GetRowMarker(size_t itemIndex) const
{
	long	marker	= 0;
	if ( itemIndex < farrIndexToMarker.size() ) {
		marker	= farrIndexToMarker[ itemIndex ];
	}

	return marker;
}

void VWListBrowserCtrl::SetRowMarker(size_t itemIndex, long marker)
{
	if ( itemIndex < farrIndexToMarker.size() ) {
		farrIndexToMarker[ itemIndex ]	= marker;
	}
}

size_t VWListBrowserCtrl::GetRowWithMarker(long marker)
{
	size_t	rowIndex	= size_t(-1);

	size_t	cnt			= farrIndexToMarker.size();
	for(size_t i=0; i<cnt; i++) {
		const long&	theMarker	= farrIndexToMarker[ i ];
		if ( theMarker == marker ) {
			rowIndex	= i;
			// FOUND ! STOP
			break;
		}
	}

	return rowIndex;
}

void VWListBrowserCtrl::SetColumnWidth(size_t fromColumn, size_t toColumn, size_t width)
{
	VERIFYN( kVStanev, ::GS_SetListBrowserColumnWidth( gCBP, fpParentDlg->GetControlID(), fControlID, DemoteTo<short> ( kVStanev, fromColumn ), DemoteTo<short> ( kVStanev, toColumn ), DemoteTo<short> ( kVStanev, width ) ) );
}

void VWListBrowserCtrl::GetColumnWidth(size_t column, short &width)
{
	VERIFYN( kVStanev, ::GS_GetListBrowserColumnWidth( gCBP, fpParentDlg->GetControlID(), fControlID, column, width ) );
}

void VWListBrowserCtrl::EnableDropOnIndices(size_t startItemIndex, size_t endItemIndex, bool enable)
{
	VERIFYN( kVStanev, ::GS_EnableListBrowserDropOnIndices( gCBP, fpParentDlg->GetControlID(), fControlID, DemoteTo<int> ( kVStanev, startItemIndex ), DemoteTo<int> ( kVStanev, endItemIndex ), enable ) );
}

size_t VWListBrowserCtrl::GetFirstSelected() const
{
	size_t	row		= 0;
	bool	ok		= this->GetNextRowSelected( row );
	if ( ! ok )
		row		= (size_t) -1;
	return row;
}

bool VWListBrowserCtrl::GetNextSelected(size_t& row) const
{
	row++;
	return this->GetNextRowSelected( row );
}

bool VWListBrowserCtrl::GetNextRowSelected(size_t& row) const
{
	size_t	itemsCnt = this->GetRowsCount();
	while ( row < itemsCnt && ! this->IsRowSelected( row ) ) {
		row++;
	}
	return row < itemsCnt;
}

// ------------------------------------------------------------------------
// columns
VWListBrowserColumn VWListBrowserCtrl::GetColumn(size_t columnIndex)
{
	VWListBrowserColumn column( fpParentDlg->GetControlID(), fControlID, DemoteTo<short>( kVStanev, columnIndex ) );
	return column;
}

VWListBrowserColumn VWListBrowserCtrl::AddColumn(const TXString& text, size_t width)
{
	short	columnIndex	= ::GS_GetNumListBrowserColumns( gCBP, fpParentDlg->GetControlID(), fControlID );
	::GS_InsertListBrowserColumn( gCBP, fpParentDlg->GetControlID(), fControlID, columnIndex, text, DemoteTo<short>( kVStanev, width ) );
	return this->GetColumn( columnIndex );
}

VWListBrowserColumn VWListBrowserCtrl::InsertColumn(size_t columnIndex, const TXString& text, size_t width)
{
	::GS_InsertListBrowserColumn( gCBP, fpParentDlg->GetControlID(), fControlID, DemoteTo<short>( kVStanev, columnIndex ), text, DemoteTo<short>( kVStanev, width ) );
	return this->GetColumn( columnIndex );
}

void VWListBrowserCtrl::DeleteColumn(size_t columnIndex)
{
	VERIFYN( kVStanev, ::GS_DeleteListBrowserColumn( gCBP, fpParentDlg->GetControlID(), fControlID, DemoteTo<short>( kVStanev, columnIndex ) ) );
}

size_t VWListBrowserCtrl::GetColumnsCount() const
{
	return (size_t) ::GS_GetNumListBrowserColumns( gCBP, fpParentDlg->GetControlID(), fControlID );
}

void VWListBrowserCtrl::EnableColumnLines(bool enable)
{
	::GS_EnableListBrowserColumnLines( gCBP, fpParentDlg->GetControlID(), fControlID, enable );
}

bool VWListBrowserCtrl::AreColumnLinesEnabled() const
{
	return ::GS_AreListBrowserColumnLinesEnabled( gCBP, fpParentDlg->GetControlID(), fControlID ) ? true : false;
}

// ------------------------------------------------------------------------
// items
VWListBrowserItem VWListBrowserCtrl::GetItem(size_t rowIndex, size_t columnIndex)
{
	// assert that we have such column
	ASSERTN( kVStanev, columnIndex < (size_t) ::GS_GetNumListBrowserColumns( gCBP, fpParentDlg->GetControlID(), fControlID ) );

	TXString	strEmpty;
	size_t		rowsCnt		= ::GS_GetNumListBrowserItems( gCBP, fpParentDlg->GetControlID(), fControlID );
	if ( rowsCnt != (size_t) -1 ) {
		for(size_t i=rowsCnt; i<=rowIndex; i++) {
			size_t	newRowIndex	= ::GS_InsertListBrowserItem( gCBP, fpParentDlg->GetControlID(), fControlID, i, strEmpty );

			// set marker for this item
			if ( newRowIndex >= farrIndexToMarker.size() ) {
				// make sure we have enough space for the marker of this element
				farrIndexToMarker.resize( newRowIndex + 1 );
			}
		}
	}

	VWListBrowserItem item ( fpParentDlg->GetControlID(), fControlID, DemoteTo<short>( kVStanev, columnIndex ), DemoteTo<short>( kVStanev, rowIndex ) );
	return item;
}

// ------------------------------------------------------------------------
// rows
bool VWListBrowserCtrl::IsRowSelected(size_t rowIndex) const
{
	return ::GS_IsListBrowserItemSelected( gCBP, fpParentDlg->GetControlID(), fControlID, DemoteTo<short> ( kVStanev, rowIndex ) ) ? true : false;
}

size_t VWListBrowserCtrl::AddRow(const TXString& text, long marker /*=0*/)
{
	short	rowIndex	= ::GS_GetNumListBrowserItems( gCBP, fpParentDlg->GetControlID(), fControlID );

	// set marker for this item
	if ( rowIndex >= 0 && size_t(rowIndex) >= farrIndexToMarker.size() ) {
		// make sure we have enough space for the marker of this element
		farrIndexToMarker.resize( rowIndex + 1 );
	}

	farrIndexToMarker[ rowIndex ]	= marker;

	return ::GS_InsertListBrowserItem( gCBP, fpParentDlg->GetControlID(), fControlID, rowIndex, text );
}

size_t VWListBrowserCtrl::InsertRow(size_t rowIndex, const TXString& text, long marker /*=0*/)
{
	size_t	newRowIndex	= ::GS_InsertListBrowserItem( gCBP, fpParentDlg->GetControlID(), fControlID, DemoteTo<short> ( kVStanev, rowIndex ), text );

	// set marker for this item
	if ( newRowIndex >= farrIndexToMarker.size() ) {
		// make sure we have enough space for the marker of this element
		farrIndexToMarker.resize( newRowIndex + 1 );
	}

	farrIndexToMarker[ newRowIndex ]	= marker;

	return newRowIndex;
}

void VWListBrowserCtrl::DeleteRow(size_t rowIndex)
{
	DSTOPIF( rowIndex >= this->GetRowsCount(), (kVStanev, "Deleting row = %d that doesn't exist in VWListBrowserCtrl", rowIndex) );

	ASSERTN( kVStanev, rowIndex < farrIndexToMarker.size() );
	if ( rowIndex < farrIndexToMarker.size() ) {
		farrIndexToMarker.erase( farrIndexToMarker.begin() + rowIndex );
	}
	VERIFYN( kVStanev, ::GS_DeleteListBrowserItem( gCBP, fpParentDlg->GetControlID(), fControlID, DemoteTo<short> ( kVStanev, rowIndex ) ) );
}

void VWListBrowserCtrl::DeleteAllRows()
{
	farrIndexToMarker.clear();
	VERIFYN( kVStanev, ::GS_DeleteAllListBrowserItems( gCBP, fpParentDlg->GetControlID(), fControlID ) );
}

size_t VWListBrowserCtrl::GetRowsCount() const
{
	size_t	cntCount	= ::GS_GetNumListBrowserItems( gCBP, fpParentDlg->GetControlID(), fControlID );
	if ( cntCount == (size_t) -1 )
		cntCount	= 0;
	return cntCount;
}

// ------------------------------------------------------------------------
// images support
size_t VWListBrowserCtrl::AddImage(size_t resourceID, size_t resourceIDSelected /*=0*/)
{
	return (size_t) ::GS_AddListBrowserImage( gCBP, fpParentDlg->GetControlID(), fControlID, kResourceSmallIcon, DemoteTo<short> ( kVStanev, resourceID ), DemoteTo<short> ( kVStanev, resourceIDSelected ) );
}

size_t VWListBrowserCtrl::AddImageStandard(EStandardImageID image, EStandardImageID selImage)
{
#define GET_IMAGE_RESID(x, res) { switch( x ) {		\
			case kStandardImageID_None:					res = 0;			break;	\
			case kStandardImageID_Blank:				res = 10331;		break;	\
			case kStandardImageID_DiamondBlack:			res = 1485;			break;	\
			case kStandardImageID_DiamondHollow:		res = 1486;			break;	\
			case kStandardImageID_DiamondGray:			res = 1487;			break;	\
			case kStandardImageID_RedCrossedCircle:		res = 1488;			break;	\
			case kStandardImageID_CheckMark:			res = 1493;			break;	\
			case kStandardImageID_CheckMarkWhite:		res = 1533;			break;	\
			case kStandardImageID_LeftBlackArrow:		res = 1534;			break;	\
			case kStandardImageID_RightBlackArrow:		res = 1535;			break;	\
			case kStandardImageID_LeftHollowArrow:		res = 1536;			break;	\
			case kStandardImageID_RightHollowArraw:		res = 1537;			break;	\
			case kStandardImageID_LeftThinArrow:		res = 1538;			break;	\
			case kStandardImageID_RightThinkArrow:		res = 1539;			break;	\
			case kStandardImageID_BallBlack:			res = 1540;			break;	\
			case kStandardImageID_BallHollow:			res = 1541;			break;	\
			case kStandardImageID_Slash:				res = 1542;			break;	\
			case kStandardImageID_XMark:				res = 1543;			break;	\
			default:									res = 0;			break; } }

	short	theImage	= 0;
	short	theSelImage	= 0;

	GET_IMAGE_RESID( image, theImage );
	GET_IMAGE_RESID( selImage, theSelImage );

	return (size_t) ::GS_AddListBrowserImage( gCBP, fpParentDlg->GetControlID(), fControlID, kResourceSmallIcon, theImage, theSelImage );
}
