/////////////////////////////////////////////////////////////////////////////
// Name:        No names yet.
// Purpose:     Contrib. demo
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     ??/10/98
// RCS-ID:      $Id$
// Copyright:   (c) Aleksandras Gluchovas
// Licence:   	wxWindows license
/////////////////////////////////////////////////////////////////////////////

#ifdef __GNUG__
#pragma implementation "dyntbar.cpp"
#pragma interface "dyntbar.cpp"
#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/utils.h"     // import wxMin,wxMax macros

#include "dyntbar.h"
#include "newbmpbtn.h"

IMPLEMENT_DYNAMIC_CLASS(wxDynamicToolBar, wxToolBarBase)

BEGIN_EVENT_TABLE( wxDynamicToolBar, wxToolBarBase )

	EVT_SIZE ( wxDynamicToolBar::OnSize  )
	EVT_PAINT( wxDynamicToolBar::OnPaint )
	//EVT_ERASE_BACKGROUND( wxDynamicToolBar::OnEraseBackground )

END_EVENT_TABLE()

/***** Implementation for class wxDynToolInfo *****/
		
IMPLEMENT_DYNAMIC_CLASS(wxDynToolInfo, wxToolLayoutItem)

/***** Implementation for class wxDynamicToolBar *****/

wxDynamicToolBar::wxDynamicToolBar()
	: mpLayoutMan( NULL ),
	  mSepartorSize( 8 ),
	  mVertGap ( 0 ),
	  mHorizGap( 0 )
{
}

wxDynamicToolBar::wxDynamicToolBar(wxWindow *parent, const wxWindowID id, 
								   const wxPoint& pos, const wxSize& size,
								   const long style, const int orientation,
								   const int RowsOrColumns, const wxString& name )
	: mpLayoutMan( NULL ),
	  mSepartorSize( 8 ),
	  mVertGap ( 0 ),
	  mHorizGap( 0 )
{
	Create(parent, id, pos, size, style, orientation, RowsOrColumns, name);

	SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_3DFACE) );
}

bool wxDynamicToolBar::Create(wxWindow *parent, const wxWindowID id, 
						      const wxPoint& pos, 
							  const wxSize& size,
							  const long style, 
							  const int orientation, const int RowsOrColumns, 
							  const wxString& name)
{
	// cut&pasted from wxtbatsmpl.h

	if ( ! wxWindow::Create(parent, id, pos, size, style, name) )
		return FALSE;

	SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_3DFACE ));

	return TRUE;
}

bool wxDynamicToolBar::Realize(void)
{
	// FOR NOW:: nothing
	return TRUE;
}

wxDynamicToolBar::~wxDynamicToolBar(void)
{
	if ( mpLayoutMan ) delete mpLayoutMan;

	for( size_t i = 0; i != mTools.Count(); ++i )
	
		delete mTools[i];
}

void wxDynamicToolBar::AddTool( int toolIndex, 
								wxWindow* pToolWindow, 
								const wxSize& size
						      )
{
	wxDynToolInfo* pInfo = new wxDynToolInfo();

	pInfo->mpToolWnd    = pToolWindow;
	pInfo->mIndex       = toolIndex;
	pInfo->mIsSeparator	= FALSE;

	int x,y;
	pToolWindow->GetSize( &x, &y );
	pInfo->mRealSize.x = x;
	pInfo->mRealSize.y = y;
	pInfo->mRect.width = x;
	pInfo->mRect.height = y;

	mTools.Add( pInfo );
}

void wxDynamicToolBar::AddTool( int toolIndex, 
								const wxString& imageFileName,
								int imageFileType, 
								const wxString& labelText, bool alignTextRight,
								bool isFlat )
{
	wxNewBitmapButton* pBtn =

	  new wxNewBitmapButton( imageFileName, imageFileType,
							 labelText, 
							 ( alignTextRight ) 
							 ? NB_ALIGN_TEXT_RIGHT 
							 : NB_ALIGN_TEXT_BOTTOM,
							 isFlat
						   );

	pBtn->Create( this, toolIndex );

	pBtn->Reshape();
	
	AddTool( toolIndex, pBtn );
}
void wxDynamicToolBar::AddTool( int toolIndex, wxBitmap labelBmp,
								const wxString& labelText, bool alignTextRight,
								bool isFlat )
{
	wxNewBitmapButton* pBtn =

	  new wxNewBitmapButton( labelBmp,
							 labelText, 
							 ( alignTextRight ) 
							 ? NB_ALIGN_TEXT_RIGHT 
							 : NB_ALIGN_TEXT_BOTTOM,
							 isFlat
						   );

	pBtn->Create( this, toolIndex );

	pBtn->Reshape();
	
	AddTool( toolIndex, pBtn );
}


  wxToolBarTool* 
	  wxDynamicToolBar::AddTool(const int toolIndex, const wxBitmap& bitmap, 
								const wxBitmap& pushedBitmap,
								const bool toggle, const long xPos, 
								const long yPos, wxObject *clientData,
								const wxString& helpString1, const wxString& helpString2)
{
	wxNewBitmapButton* pBmpBtn = new wxNewBitmapButton( bitmap );

	pBmpBtn->Create( this, toolIndex );

	pBmpBtn->Reshape();

	AddTool( toolIndex, pBmpBtn );

	return NULL;
}


wxDynToolInfo* wxDynamicToolBar::GetToolInfo( int toolIndex )
{
	for( size_t i = 0; i != mTools.Count(); ++i )

		if ( mTools[i]->mIndex == toolIndex ) return mTools[i];

	return NULL;
}

void wxDynamicToolBar::RemveTool( int toolIndex )
{
	for( size_t i = 0; i != mTools.Count(); ++i )
	
		if ( mTools[i]->mIndex == toolIndex ) 
		{
			if ( mTools[i]->mpToolWnd )

				mTools[i]->mpToolWnd->Destroy();

			mTools.Remove( i );

			Layout();

			return;
		}

	// TODO:: if not found, should it be an assertion?
}

void wxDynamicToolBar::AddSeparator( wxWindow* pSepartorWnd )
{
	wxDynToolInfo* pInfo = new wxDynToolInfo();

	pInfo->mpToolWnd    = pSepartorWnd;
	pInfo->mIndex       = -1;
	pInfo->mIsSeparator	= TRUE;

	if ( pSepartorWnd )
	{
		pSepartorWnd->Create( this, -1 );

		int x,y;
		pSepartorWnd->GetSize( &x, &y );
		pInfo->mRealSize.x = x;
		pInfo->mRealSize.y = y;

		pInfo->mRect.width = x;
		pInfo->mRect.height = y;
	}
	else
	{
		pInfo->mRealSize.x = mSepartorSize;
		pInfo->mRealSize.y = 0;

		pInfo->mRect.width  = mSepartorSize;
		pInfo->mRect.height = 0;
	}

	mTools.Add( pInfo );
}

void wxDynamicToolBar::OnEraseBackground( wxEraseEvent& event )
{
	// FOR NOW:: nothing
}

void wxDynamicToolBar::OnSize( wxSizeEvent& event )
{
	//SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_3DFACE ) );

	Layout();
}

void wxDynamicToolBar::DrawSeparator( wxDynToolInfo& info, wxDC& dc )
{
	// check the orientation of separator
	if ( info.mRect.width < info.mRect.height )
	{
		int midX = info.mRect.x + info.mRect.width/2 - 1;

		dc.SetPen( *wxGREY_PEN );
		dc.DrawLine( midX, info.mRect.y,
			         midX, info.mRect.y + info.mRect.height+1 );

		dc.SetPen( *wxWHITE_PEN );
		dc.DrawLine( midX+1, info.mRect.y,
			         midX+1, info.mRect.y + info.mRect.height+1 );
	}
	else
	{
		int midY = info.mRect.y + info.mRect.height/2 - 1;

		dc.SetPen( *wxGREY_PEN );
		dc.DrawLine( info.mRect.x, midY,
			         info.mRect.x + info.mRect.width+1, midY );

		dc.SetPen( *wxWHITE_PEN );
		dc.DrawLine( info.mRect.x, midY + 1,
			         info.mRect.x + info.mRect.width+1, midY + 1 );
	}
}

void wxDynamicToolBar::OnPaint( wxPaintEvent& event )
{
	// draw separators if any

	wxPaintDC dc(this);

	for( size_t i = 0; i != mTools.Count(); ++i )
	
		if ( mTools[i]->mIsSeparator ) 
		{
			// check if separator doesn't have it's own window
			// if so, then draw it using built-in drawing method

			if ( !mTools[i]->mpToolWnd )

				DrawSeparator( *mTools[i], dc );
		}
}

// FOR NOW:: quick fix
#include "wx/choice.h"

void wxDynamicToolBar::SizeToolWindows()
{
	for( size_t i = 0; i != mTools.Count(); ++i )
	{
		wxDynToolInfo& info = *mTools[i];

		if ( !info.mIsSeparator ) 
		{

			// center real rectangle within the rectangle 
			// provided by the layout manager

			int x = info.mRect.x;
			int y = info.mRect.y + (info.mRect.height - info.mRealSize.y)/2;

			// FOR NOW FOR NOW:: quick & dirty fix
			if ( info.mpToolWnd->IsKindOf( CLASSINFO( wxChoice ) ) )
			{
				info.mpToolWnd->SetSize( x,y, 
										info.mRealSize.x - 3, 
										info.mRealSize.y);
			}
			else
				info.mpToolWnd->SetSize( x,y, 
										info.mRealSize.x, 
										info.mRealSize.y );
		}

		// TBD:: size separator window if present
	}
}

bool wxDynamicToolBar::Layout()
{
	if ( !mpLayoutMan ) mpLayoutMan = CreateDefaulLayout();

	int x,y;
	GetSize( &x, &y );
	wxSize wndDim(x,y);
	wxSize result;

	wxLayoutItemArrayT items;

	// safe conversion
	for( size_t i = 0; i != mTools.Count(); ++i ) items.Add( mTools[i] );

	mpLayoutMan->Layout( wndDim, result, items, mVertGap, mHorizGap );;

	SizeToolWindows();
    return TRUE;
}

void wxDynamicToolBar::GetPreferredDim( const wxSize& givenDim, wxSize& prefDim )
{
	if ( !mpLayoutMan ) mpLayoutMan = CreateDefaulLayout();

	wxLayoutItemArrayT items;

	// safe conversion
	for( size_t i = 0; i != mTools.Count(); ++i ) items.Add( mTools[i] );

	mpLayoutMan->Layout( givenDim, prefDim, items, mVertGap, mHorizGap );;
}

void wxDynamicToolBar::SetLayout( LayoutManagerBase* pLayout )
{
	if ( mpLayoutMan ) delete mpLayoutMan;

	mpLayoutMan = pLayout;

	Layout();
}

void wxDynamicToolBar::EnableTool(const int toolIndex, const bool enable )
{
	wxDynToolInfo* pInfo = GetToolInfo( toolIndex );

	if ( !pInfo ) return;

	if ( pInfo->mIsSeparator || !pInfo->mpToolWnd ) return;

	pInfo->mpToolWnd->Enable( enable );
}

/***** Implementation for class BagLayout *****/

void BagLayout::Layout(  const wxSize&       parentDim, 
						 wxSize&	         resultingDim,
						 wxLayoutItemArrayT& items,
						 int		         horizGap,
 		                 int		         vertGap  
					  )
{
	int maxWidth = 0;
	int curY  = 0;
	int nRows = 0;

	size_t i = 0;

	while( i < items.Count() )
	{
		int curX   = 0;
		int height = 0;
		int nItems = 0;

		int firstItem  = i;
		int itemsInRow = 0;

		if ( nRows > 0 ) curY += vertGap;

		// step #1 - arrange horizontal positions of items in the row

		do
		{
			if ( itemsInRow > 0 ) curX += horizGap;

			wxRect& r = items[i]->mRect;

			if ( curX + r.width > parentDim.x )

				if ( itemsInRow > 0 ) break;

			r.x = curX;
			r.y = curY;

			curX += r.width;

			height = wxMax( height, r.height );

			++itemsInRow;
			++i;

		} while( i < items.Count() );

		curY += height;

		maxWidth = wxMax( maxWidth, curX );
	}

	resultingDim.x = maxWidth;
	resultingDim.y = curY;
}
