void EGridCtrl::AddRow( IGridRow* pRowHost )
{
	//
	// collect properties (columns) for the row
	//

	Row* pRow = new Row( pRowHost );
	pRowHost->GetGridColumns( *pRow );
	pRowHost->m_pGridCtrl = this;

	//
	//  prepare the dc for size calculations
	//

	CDC* pDC = GetDC();
	pDC->SelectObject( &m_Font );

	//
	//
	//
	
	pRow->m_nHeight = GetRowHeight( pRow , pDC );
	m_vRows.push_back( pRow );

	//
	// update column list
	//

	std::list<Row*>::iterator iter = m_vRows.begin();
	std::list<Row*>::iterator iend = m_vRows.end();

	while( iter != iend )	//for all rows...
	{
		Row* pRow = *iter;

		ASSERT( pRow->GetTabCount()==1 );
		ASSERT( pRow->GetActiveTab()==0 );

		int n = pRow->Size();

		for( int i=0 ; i<n ; i++ )
		{
			EProperty* pProperty = pRow->Get(i);

			int m = EIconTextButtonProperty::s_nMargin;

			CString sName   = pProperty->GetName();
			Column* pColumn = GetColumn( sName , true , m + pDC->GetTextExtent(sName).cx + m );
			pColumn->EnsureWidth( pProperty->GetPreferedWidth(pDC) );
		}

		iter++;
	}

	ReleaseDC(pDC);

	//
	// calculate left of each column
	//

	RefreshColumnLefts( m_ViewportOrg.x );
	RefreshRowTops( m_ViewportOrg.y );

	//
	//
	//

	BuildPropertyMap();

	//
	//
	//

	Invalidate();

}
void EGridCtrl::DoPaint( CDC* pDC )
{
	CPoint vpo;
	vpo.y = -GetScrollPos(SB_VERT);
	vpo.x = -GetScrollPos(SB_HORZ);

	m_ViewportOrg = vpo;

	CRect cr;
	GetClientRect(&cr);

	pDC->SelectObject( &m_Font );
	pDC->SetBkMode(TRANSPARENT);

	//
	// clear bg
	//

	pDC->FillSolidRect( &cr , RGB(255,255,255) );

//pDC->MoveTo(0,0);
//pDC->LineTo(200,100);

//	BITMAPINFO bmi;
//	bmi.bmiHeader.biBitCount      = 32;
//	bmi.bmiHeader.biClrImportant  = 0;
//	bmi.bmiHeader.biClrUsed       = 0;
//	bmi.bmiHeader.biCompression   = BI_RGB;
//	bmi.bmiHeader.biHeight        = 100;
//	bmi.bmiHeader.biPlanes        = 1;
//	bmi.bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
//	bmi.bmiHeader.biSizeImage     = 0;			//0 is ok for BI_RGB (uncompressed)
//	bmi.bmiHeader.biWidth         = 100;
//	bmi.bmiHeader.biXPelsPerMeter = 1;
//	bmi.bmiHeader.biYPelsPerMeter = 1;

//	StretchDIBits( pDC->GetSafeHdc() , 0 , 100-1 , 100 , -100 , 0 , 0 , 100 , 100 , pBuffer , &bmi , DIB_RGB_COLORS , SRCCOPY );
//	SetDIBitsToDevice( pDC->GetSafeHdc() , 0 , 0 , 100 , 100 , 0 , 0 , 0 , 100 , pBuffer , &bmi , DIB_RGB_COLORS );


	//
	//
	//

	RefreshColumnLefts( vpo.x );
	RefreshRowTops( vpo.y + GetHeaderRowHeight() + m_nColumnSeperatorWidth );

	//
	//
	//

	std::list<Column*>::iterator coliter;
	std::list<Column*>::iterator coliend;

	//
	// draw all rows
	//

//--------

//	CRect r( 0 , 0 ,0 , 0 );
//
//	std::list<Row*>::iterator iter = m_vRows.begin();
//	std::list<Row*>::iterator iend = m_vRows.end();
//
//	while( iter != iend )
//	{
//		Row* pRow = *iter;
//
//		ASSERT( pRow->GetTabCount()==1 );
//		ASSERT( pRow->GetActiveTab()==0 );
//
//		r.top    = pRow->m_nTop;
//		r.bottom = pRow->m_nTop + pRow->m_nHeight;
//
//		coliter = m_vCols.begin();
//		coliend = m_vCols.end();
//
//		while( coliter != coliend )
//		{
//			Column* pColumn = *coliter;
//
//			EProperty* pProperty = pRow->GetProperty( pColumn->m_sName );
//
//			if( pProperty != NULL )
//			{
//				r.left  = pColumn->m_nLeft;
//				r.right = pColumn->m_nLeft + pColumn->m_nWidth;
//				pProperty->Draw( &dc , this , &r );
//			}
//
//
//
//			coliter++;
//		}
//		
//		r.top = r.bottom + m_nColumnSeperatorWidth;
//
//		iter++;
//	}

//--------

	CRect r( 0 , 0 ,0 , 0 );

	std::list<Row*>::iterator iter = m_vRows.begin();
	std::list<Row*>::iterator iend = m_vRows.end();

	EProperty** ppMap = m_ppPropertyMap;

	while( iter != iend )
	{
		Row* pRow = *iter;

		ASSERT( pRow->GetTabCount()==1 );
		ASSERT( pRow->GetActiveTab()==0 );

		r.top    = pRow->m_nTop;
		r.bottom = pRow->m_nTop + pRow->m_nHeight;

		coliter = m_vCols.begin();
		coliend = m_vCols.end();

		while( coliter != coliend )
		{
			Column* pColumn = *coliter;

			EProperty* pProperty = *ppMap;	//pRow->GetProperty( pColumn->m_sName );

			if( pProperty != NULL )
			{
				r.left  = pColumn->m_nLeft;
				r.right = pColumn->m_nLeft + pColumn->m_nWidth;
				pProperty->m_Rect = r;
				pProperty->Draw( pDC , this );
			}

			ppMap++;

			coliter++;
		}
		
		r.top = r.bottom + m_nColumnSeperatorWidth;

		iter++;
	}

//pDC->MoveTo(0,0);
//pDC->LineTo(500,500);
//pDC->FillSolidRect( 0 , 0 , 80 , 80 , RGB(255,240,240) );

//--------

	//
	// vertical grid lines
	//

	pDC->SelectStockObject(BLACK_PEN);

	if( m_vCols.size() > 0 )
	{
		coliter = m_vCols.begin();
		coliend = m_vCols.end();

		Row* pLastRow = m_vRows.back();

		int y0 = 0;
		int y1 = pLastRow->m_nTop + pLastRow->m_nHeight;

		while( coliter != coliend )
		{
			Column* pColumn = *coliter;

			int x = pColumn->m_nLeft + pColumn->m_nWidth;

			pDC->MoveTo( x , y0 );
			pDC->LineTo( x , y1 );

			coliter++;
		}
	}

	//
	// horizontal grid lines
	//
	
	if( m_vRows.size() > 0 )
	{
		iter = m_vRows.begin();
		iend = m_vRows.end();

		Column* pLastCol = m_vCols.back();

		int x0 = 0;
		int x1 = pLastCol->m_nLeft + pLastCol->m_nWidth;

		pDC->MoveTo( x0 , GetHeaderRowHeight() );
		pDC->LineTo( x1 , GetHeaderRowHeight() );

		while( iter != iend )
		{
			Row* pRow = *iter;

			int y = pRow->m_nTop + pRow->m_nHeight;

			pDC->MoveTo( x0 , y );
			pDC->LineTo( x1 , y );

			iter++;
		}
	}

	//
	// print column headers
	//

//	pDC->SetViewportOrg(0,0);

	r.SetRect(0,0,0,GetHeaderRowHeight());

	coliter = m_vCols.begin();
	coliend = m_vCols.end();

	while( coliter != coliend )
	{
		//   0    1                      2    3      4    5
		//   +----+----------------------+----+------+----+
		//   |    |                      |    |      |    |
		//   |    | column text          |    | sort |    |
		//   |    |                      |    |      |    |
		//   +----+----------------------+----+------+----+
		//

		Column* pColumn = *coliter;

		int x0 = pColumn->m_nLeft;
		int x1 = x0 + EIconTextButtonProperty::s_nMargin;

		int x5 = pColumn->m_nLeft + pColumn->m_nWidth;
		int x4 = x5 - EIconTextButtonProperty::s_nMargin;

		int x3 = x4;
		int x2 = x4;

		if( pColumn->m_nSortState != 0 )
		{
			x3 = x4 - 8;
			x2 = x3 - EIconTextButtonProperty::s_nMargin;
		}

		//
		// fill background
		//

		r.left  = x0;
		r.right = x5;
		pDC->FillSolidRect( &r , GetColorPaneKey() );

		//
		// text
		//

		r.left  = x1;
		r.right = x2;
		int nRequired = r.Width();
		CString s = EPropWnd::s_FitStringToWidth( pColumn->m_sName , nRequired , pDC );
		pDC->DrawText( s , &r , DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_NOCLIP );

		//
		// draw sort state triangle
		//

		if( pColumn->m_nSortState != 0 )
		{
			if( x3>=x1 )
			{
				CBrush brush;
				brush.CreateSolidBrush( RGB(100,100,100) );
				pDC->SelectObject(&brush);
				pDC->SelectStockObject(BLACK_PEN);

	//			CRect trianglerect = r;
	//			trianglerect.left = trianglerect.right - 10 - 4;
	//			trianglerect.right = trianglerect.left + 10;
	//			trianglerect.top += 8;
	//			trianglerect.bottom -= 8;
	//			DrawFrame( pDC , trianglerect , false , RGB(200,180,180) );

				pDC->SetViewportOrg( x3 , GetHeaderRowHeight()/2 );

				POINT points[] =
				{
					{ 0 ,-2 },
					{ 8 ,-2 },
					{ 4 ,2 }
				};

				if( pColumn->m_nSortState == 2 )
				{
					points[0].y *= -1;
					points[1].y *= -1;
					points[2].y *= -1;
				}

				pDC->Polygon( points , 3 );

				pDC->SetViewportOrg( 0 , 0 );
			}
		}

		coliter++;
	}

}