////////////////////////////////////////////////////////////////////////////
// Name:        No names yet.
// Purpose:     Contrib. demo
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     2000/02/08
// RCS-ID:      $Id: treesplit.cpp,v 1.4 2001/03/14 13:48:11 aleksandras Exp $
// Copyright:   (c) Aleksandras Gluchovas
// Licence:   	GPL (version 2.0 or later)
/////////////////////////////////////////////////////////////////////////////

#ifdef __GNUG__
    #pragma implementation "pmcmn.cpp"
    #pragma interface "pmcmn.h"
#endif

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#include "wx/pmf/treesplit.h"
#include "wx/debug.h"

/***** Implementation for class wxTSImageInfo *****/

wxTSImageInfo::wxTSImageInfo( wxBitmap bmp, int id, const wxColour maskCol )

	: mImageId( id ),
	  mActualId( id ),
	  mBitmap( bmp ),
	  mMaskCol( maskCol )
{}

void wxTSImageInfo::SetId( int id ) 
{ 
	mImageId = id; 
}

int wxTSImageInfo::GetId() 
{ 
	return mImageId; 
}

/***** Implementation for class wxTSItemData *****/

wxTSItemData::wxTSItemData()

	: mpObject( NULL ),
	  mpHandler( NULL ),
	  mType( 0 )
{}

wxTSItemData::wxTSItemData( wxObject* pObject, wxTSBranchHandler* pHandler, int type )

	: mpObject( pObject ),
	  mpHandler( pHandler ),
	  mType( type )
{}

wxTSItemData::~wxTSItemData()
{}

wxTSItemData* wxTSItemData::Clone()
{
	wxTSItemData* pCopy = new wxTSItemData();

	pCopy->SetId( this->GetId() );

	pCopy->mpObject = mpObject;
	pCopy->mpHandler = mpHandler;

	return pCopy;
}

void wxTSItemData::SetObject( wxObject* pObj )
{
	mpObject = pObj;
}

wxObject* wxTSItemData::GetObject()
{
	return mpObject;
}

void wxTSItemData::SetHandler( wxTSBranchHandler* pHandler )
{
	mpHandler = pHandler;
}

wxTSBranchHandler* wxTSItemData::GetHandler()
{
	return mpHandler;
}

void wxTSItemData::SetType( int type )
{
	mType = type;
}

int wxTSItemData::GetType()
{
	return mType;
}

/***** Implementation for class wxTSBranchHandler *****/

void wxTSBranchHandler::SetTree( wxTSTree* pHolder )
{
	mpTree = pHolder;
}

wxTSTree* wxTSBranchHandler::GetTree()
{
	return mpTree;
}

void wxTSBranchHandler::SetOwnedBranchItem( wxTreeItemId item )
{
	mBranchItem = item;
}

wxTreeItemId wxTSBranchHandler::GetOwnedBranchItem()
{
	return mBranchItem;
}

void wxTSBranchHandler::OnAddItemsToPopup( wxMenu* pMenu )
{
	// nothing by default
}

void wxTSBranchHandler::OnBranchItemExpanding( wxTreeItemId, wxTSItemData* pData )
{
	// nothing by default
}

void wxTSBranchHandler::OnSelectionChanged( wxTreeItemId id, wxTSItemData* pData )
{
	// nothing by default
}

/***** Implementation for class wxTSTree *****/

IMPLEMENT_DYNAMIC_CLASS( wxTSTree, wxTreeCtrl )

BEGIN_EVENT_TABLE( wxTSTree, wxTreeCtrl )

	EVT_TREE_KEY_DOWN      ( SPLIT_TREECTRL_ID, wxTSTree::OnKeyDown )
	EVT_TREE_BEGIN_DRAG    ( SPLIT_TREECTRL_ID, wxTSTree::OnBeginDrag )
	EVT_TREE_ITEM_EXPANDING( SPLIT_TREECTRL_ID, wxTSTree::OnItemExpanding )

	EVT_TREE_SEL_CHANGING( SPLIT_TREECTRL_ID, wxTSTree::OnSelectionChanging )
	EVT_TREE_SEL_CHANGED ( SPLIT_TREECTRL_ID, wxTSTree::OnSelectionChanged  )

	EVT_RIGHT_DOWN ( wxTSTree::OnRightClick  )
	EVT_LEFT_UP    ( wxTSTree::OnLeftMouseUp )
	EVT_LEFT_DCLICK( wxTSTree::OnDblClick    )
	EVT_MIDDLE_DOWN( wxTSTree::OnMiddleClick )

	EVT_COMMAND_RANGE( 0, 50000, wxEVT_COMMAND_MENU_SELECTED, wxTSTree::OnCommandEvent )

END_EVENT_TABLE()

wxTSTree::wxTSTree()

	: mpImgList( NULL ),
	  mImgListUpdatePending( FALSE )
{}

wxTSTree::wxTSTree( wxWindow* pParent, wxWindowID id )

	: wxTreeCtrl( pParent, id ),
	  mpImgList( NULL ),
	  mImgListUpdatePending( FALSE )
{}

wxTSTree::~wxTSTree()
{
	if ( mpImgList ) delete mpImgList;

	WX_CLEAR_ARRAY( mHandlers );
}

void wxTSTree::RegisterHandler( wxTSBranchHandler* pHandler )
{
	wxTSHandlerInfo* pInfo = new wxTSHandlerInfo();

	pInfo->mpHandler = pHandler;

	mHandlerHash.Put( (long)pHandler, (wxObject*)pInfo );

	mHandlers.Add( pInfo );

	pHandler->SetTree( this );
}

void wxTSTree::RegisterIcons( TSImageInfoListT& lst, wxTSBranchHandler* pHandler )
{
	wxTSHandlerInfo* pInfo = (wxTSHandlerInfo*)mHandlerHash.Get( (long)pHandler );

	wxASSERT( pInfo ); // DBG::

	WX_CLEAR_ARRAY( pInfo->mImages );
	pInfo->mImages = lst;

	mImgListUpdatePending = TRUE;
}

void wxTSTree::HashObject( wxObject* pObj, wxTreeItemId itemId )
{
	mObjectHash.Put( (long)pObj, (wxObject*)(long)itemId );
}

void wxTSTree::UnHashObject( wxObject* pObj )
{

	mObjectHash.Delete( (long)pObj );
}

wxTreeItemId wxTSTree::AddTSRoot( const wxString& text,
									int image, int selImage, wxTSItemData* pData )
{
	wxTSBranchHandler* pHandler = pData ? pData->GetHandler() : NULL;

	wxTreeItemId id = AddRoot( text,	
							   GetActualImageId( image, pHandler), 
							   GetActualImageId( selImage, pHandler), pData );

	if ( pData && pData->GetObject() )

		HashObject( pData->GetObject(), id );

	return id;
}

wxTreeItemId wxTSTree::AppendTSItem( wxTreeItemId parent, const wxString& text, 
								     int image, int selImage, wxTSItemData* pData, 
									 bool localizeImageIds, int before )
{
	wxTSBranchHandler* pHandler = pData ? pData->GetHandler() : NULL;

	wxTreeItemId id;

	if ( before == -1 )

		id = AppendItem( parent, text, 
					     localizeImageIds ? GetActualImageId( image, pHandler) : image, 
						 localizeImageIds ? GetActualImageId( selImage, pHandler) : selImage, pData );
	else
		id = InsertItem( parent, before, text, 
					     localizeImageIds ? GetActualImageId( image, pHandler) : image, 
						 localizeImageIds ? GetActualImageId( selImage, pHandler) : selImage, pData );

	if ( pData && pData->GetObject() )

		HashObject( pData->GetObject(), id );

	return id;
}

void wxTSTree::ChangeItemImage( wxTreeItemId, int newImage )
{
	// TBD::
}

void wxTSTree::DeleteItem( wxTreeItemId item )
{
	wxTSItemData* pData = (wxTSItemData*)GetItemData( item );

	if ( pData ) 
	{
		if ( pData->GetObject() )

			mObjectHash.Delete( (long)pData->GetObject() );
	}

	Delete( item );
}

void wxTSTree::DeleteBranch( wxTreeItemId item )
{
	wxASSERT_MSG( item.IsOk(), "DeleteBranch() called with invalid item!" );

	wxTreeItemId child; long cookie = 0;

	child = GetFirstChild( item, cookie );

	while( child.IsOk() )
	{
		wxTreeItemId tmp = child;

		child = GetNextChild( item, cookie );

		DeleteBranch( tmp );
	}

	DeleteItem( item ); // delete item itself, after all of it's children deleted
}

wxTSItemData* wxTSTree::FindDataForObject( wxObject* pObj )
{
	long id = (long)mObjectHash.Get( (long)pObj );

	if ( id == 0 ) return NULL;

	return (wxTSItemData*)GetItemData( wxTreeItemId(id) );
}

wxTSItemData* wxTSTree::GetDataForObject( wxObject* pObj )
{
	wxTSItemData* pData = FindDataForObject( pObj );

	wxASSERT_MSG( pData != NULL, "wxTSItemData instance was not found for the given object!" );

	return pData;
}

wxTreeItemId wxTSTree::FindTreeItemForObject( wxObject* pObj )
{
	return wxTreeItemId( (long)mObjectHash.Get( (long)pObj ) );
}

wxObject* wxTSTree::GetSelectedObject()
{
	wxTSItemData* pData = 
		(wxTSItemData*)GetItemData( GetSelection() );

	wxASSERT( pData );
	wxASSERT( pData->GetObject() );

	return pData->GetObject();
}

wxTreeCtrl* wxTSTree::GetTree()
{
	return (wxTreeCtrl*)this;
}

void wxTSTree::OnKeyDown( wxTreeEvent& event )
{
}

void wxTSTree::OnDblClick( wxMouseEvent& event )
{
    int breakpoint = 1;  // just to be able to set a breakpoint
}

void wxTSTree::OnRightClick( wxMouseEvent& event )
{
	int flags = 0;

	wxPoint pos( event.GetX(), event.GetY() );

	wxTreeItemId id = HitTest( pos, flags );

	if ( id != wxTreeItemId() )
	{
		SelectItem( id );

		wxTSItemData* pData = 
			(wxTSItemData*)GetItemData( id );

		if ( !pData || !pData->GetHandler() ) return;

		wxMenu* pMenu = new wxMenu();

		pData->GetHandler()->OnAddItemsToPopup( pMenu );

		this->PopupMenu( pMenu, pos );

		delete pMenu;
	}
}

void wxTSTree::OnMiddleClick( wxMouseEvent& event )
{
}

void wxTSTree::OnMouseMove( wxMouseEvent& event )
{
}

void wxTSTree::OnLeftMouseUp( wxMouseEvent& event )
{
}

void wxTSTree::OnItemExpanding( wxTreeEvent& event )
{
	wxTSItemData* pData = (wxTSItemData*)GetItemData( event.GetItem() );

	if ( pData->GetHandler() )

		pData->GetHandler()->OnBranchItemExpanding( event.GetItem(), pData );

	event.Skip();
}

void wxTSTree::OnSelectionChanging( wxTreeEvent& event )
{
}

void wxTSTree::OnSelectionChanged( wxTreeEvent& event )
{
	wxTSItemData* pData = 
		(wxTSItemData*)GetItemData( event.GetItem() );

	if ( !pData || !pData->GetHandler() )
        return;

	if ( pData->GetHandler() )
	
		pData->GetHandler()->OnSelectionChanged( event.GetItem(), pData );
}

void wxTSTree::OnBeginDrag( wxTreeEvent& event )
{
}

void wxTSTree::OnCommandEvent( wxCommandEvent& event )
{
	wxTreeItemId sel = GetSelection();

	if ( sel == wxTreeItemId() )
	{
		event.Skip(); 
		return;
	}

	wxTSItemData* pData = 
		(wxTSItemData*)GetItemData( GetSelection() );

	if ( !pData || !pData->GetHandler() ) 
	{
		event.Skip(); 
		return;
	}

	pData->GetHandler()->GetEvtHandler()->ProcessEvent( event );
}

/*** protected methods ***/

int wxTSTree::GetActualImageId( int imgId, wxTSBranchHandler* pHandler )
{
	if ( !pHandler ) return imgId;

	wxTSHandlerInfo* pInfo = (wxTSHandlerInfo*)mHandlerHash.Get( (long)pHandler );

	if ( !pInfo ) return imgId;

	for( size_t i = 0; i != pInfo->mImages.Count(); ++i )

		if ( pInfo->mImages[i]->mImageId == imgId )

			return pInfo->mImages[i]->mActualId;

	return imgId;
}

void wxTSTree::RebuildImageList()
{
	this->SetImageList( NULL );

	if ( mpImgList )
	{
		delete mpImgList;
		mpImgList = NULL;
	}

	bool wasSet = mpImgList != NULL;

	if ( !mpImgList ) 
	
		mpImgList = new wxImageList( 16,16, TRUE, 1 );

	mpImgList->RemoveAll();

	int curId = 0;

	for( size_t i = 0; i != mHandlers.Count(); ++i )
	{
		wxTSHandlerInfo* pHandler = mHandlers[i];

		for( size_t k = 0; k != pHandler->mImages.Count(); ++k )
		{
			wxTSImageInfo* pImage = pHandler->mImages[k];

			if ( pImage->mMaskCol.Red() != 17 )

				pImage->mActualId = mpImgList->Add( pImage->mBitmap, pImage->mMaskCol );
			else
				pImage->mActualId = mpImgList->Add( pImage->mBitmap );

		}
	}

	if ( !wasSet )

		this->SetImageList( mpImgList );
}
