// aplReBar.cpp
#include "stdafx.h"
#include "apl_gui.h"
#include "resource.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

bool aplCreateResizedBitmap(CBitmap &bmptrg, CBitmap *bmpsrc, int new_cx, int new_cy)
{
	if(bmptrg.m_hObject!=0)	bmptrg.DeleteObject();
	if(bmpsrc==0 || new_cx==0 || new_cy==0) return false;
	CDC *dc_d= CWnd::GetDesktopWindow()->GetDC();
	if(0==dc_d) return false;
	CDC dc_s; dc_s.CreateCompatibleDC(dc_d);
	CDC dc_t; dc_t.CreateCompatibleDC(dc_d);
	bmptrg.CreateCompatibleBitmap(dc_d,new_cx,new_cy);
	CBitmap* pOldBitmap1 = dc_t.SelectObject(&bmptrg);
	CWnd::GetDesktopWindow()->ReleaseDC(dc_d);

	CBitmap* pOldBitmap = dc_s.SelectObject(bmpsrc);

	CSize sz=bmpsrc->GetBitmapDimension();
	BITMAP bmp;
	bmpsrc->GetBitmap(&bmp);
	dc_t.SetStretchBltMode(HALFTONE);
	dc_t.StretchBlt(0, 0, new_cx, new_cy, &dc_s,  0, 0, bmp.bmWidth, bmp.bmHeight ,SRCCOPY );

	dc_s.SelectObject(&pOldBitmap);
	dc_t.SelectObject(&pOldBitmap1);
	return true;
}


// iPecision - точность отклонения пропорций компонент цвета для преобразование в процентах 
// 0 - преобразуется только если цвет точно соответствует  100 - преобразуется почти всё

bool AFX_EXT_API aplCreateMappedBitmap(CBitmap &bmptrg, CBitmap *bmpsrc, COLORREF src_color, COLORREF trg_color, int iPecision)
{
	if(0==bmpsrc) return false;
	if(0==bmpsrc->m_hObject) return false;

	if(iPecision<0 ) iPecision=0;
	else  if(iPecision>100 ) iPecision=100;

	BITMAP bmp;
	bmpsrc->GetBitmap(&bmp);

	int w=bmp.bmWidth, h=bmp.bmHeight;
	if(w<=0 || h<=0) return false;

	CDC *dc_d= CWnd::GetDesktopWindow()->GetDC();
	if(0==dc_d) return false;

	if(bmptrg.m_hObject!=0)	bmptrg.DeleteObject();

	CDC dc_s; dc_s.CreateCompatibleDC(dc_d);
	CDC dc_t; dc_t.CreateCompatibleDC(dc_d);
	bmptrg.CreateCompatibleBitmap(dc_d,w,h);
	CBitmap* pOldBitmap1 = dc_t.SelectObject(&bmptrg);
	CWnd::GetDesktopWindow()->ReleaseDC(dc_d);

	CBitmap* pOldBitmap = dc_s.SelectObject(bmpsrc);

	//dc_t.SetStretchBltMode(HALFTONE);
	//dc_t.StretchBlt(0, 0, w, h, &dc_s,  0, 0, bmp.bmWidth, bmp.bmHeight ,SRCCOPY );

	bool bConvert=true;
	
	if(src_color==RGB(0,0,0)) src_color=dc_s.GetPixel(0,0);
	else if(src_color==RGB(255,255,255)) bConvert=false;
	
	if(src_color==trg_color ) bConvert=false;

	float sr=GetRValue(src_color);
	float sg=GetGValue(src_color);
	float sb=GetBValue(src_color);

	float tr=GetRValue(trg_color);
	float tg=GetGValue(trg_color);
	float tb=GetBValue(trg_color);

	//iPecision=150; // точность отклонения в пропорциях компоенент цвета в процентах 

	for(int i=0; i<w; i++)
	{
		for(int j=0; j<h; j++)
		{
			COLORREF pix=dc_s.GetPixel(i,j);
			if(bConvert)
			{
				if(pix==src_color) 
					pix=trg_color;
				else
				{
					int  r=GetRValue(pix);
					int  g=GetGValue(pix);
					int  b=GetBValue(pix);

					float kr= r / sr;
					float kg= g / sg;
					float kb= b / sb;

					int d1= (int)(100*(kr-kg));  if(d1<0) d1=-d1;
					int d2= (int)(100*(kr-kb));  if(d2<0) d2=-d2;
					int d3= (int)(100*(kb-kg));  if(d3<0) d3=-d3;

					//if(kr==kg && kr==kb)
					if(d1<iPecision && d2<iPecision && d3<iPecision)
					{
						//pix=RGB(255,0,0);
						pix=RGB( (int)((float)(r*tr)/sr), (int)((float)(g*tg)/sg), (int)((float)(b*tb)/sb));
					}
				}
			}
			dc_t.SetPixel(i,j,pix);
		}
	}

	dc_s.SelectObject(&pOldBitmap);
	dc_t.SelectObject(&pOldBitmap1);
	return true;
}


bool AFX_EXT_API aplLoadMappedBitmap(CBitmap &bmptrg, UINT nIDBitmap, COLORREF src_color, COLORREF trg_color, int iPecision)
{
	if(0==nIDBitmap) return false;
	CBitmap bmp;
	if(!bmp.LoadBitmap(nIDBitmap)) return false;
	bool  b= aplCreateMappedBitmap(bmptrg,&bmp,src_color,trg_color,iPecision);
	return b;
}


// direction  0 - сверху вниз, 1- слева направо
void aplDrawGradient(CDC *dc, RECT *rect, COLORREF color_from, COLORREF color_to, int direction )
{
	if(0==dc) return;
	if(0==rect) return;

	if(direction==0)  //0 - сверху вниз
	{
		int i,high=rect->bottom-rect->top,x1=rect->left,x2=rect->right,top=rect->top;
		if(high==0) return;
		//TRACE("\n\n");
		for(i=0;i<high;i++)
		{
			double k1=((double)i)/high;

			//вариант 1
			//k1=1-k1;
			//int k=(int)100* (1- k1*k1*k1);

			//вариант 2
			//int k=100-(int)(100*((1-k1)*(1-k1)));

			//вариант 3
			
			/*int k;
			if(k1<0.5)
			{
				k1=1-k1;
				k=(int)100* (k1*k1);
			}
			else
			{
				k=(int)100* (k1*k1);
			}*/

			//вариант 4
			int k;
			if(k1<0.6) k=(int)(100*k1/0.6); 
			else k=100;

			COLORREF color=aplColor_MixColor(color_from,color_to,k);

			//TRACE(" %i",k);

			CPen pen(PS_SOLID,0,color);
			CPen *oldPen=dc->SelectObject(&pen);
			dc->MoveTo(x1,top+i);
			dc->LineTo(x2,top+i);
			dc->SelectObject(oldPen);
		}
		//TRACE("\n\n");
	}
	else if(direction==1)
	{
		int i,width=rect->right-rect->left,y1=rect->top,y2=rect->bottom,left=rect->left;
		if(width==0) return;
		//TRACE("\n\n");
		for(i=0;i<width;i++)
		{
			double k1=((double)i)/width;
			int k=100-(int)(100*((1-k1)*(1-k1)));

			COLORREF color=aplColor_MixColor(color_from,color_to,k);
			CPen pen(PS_SOLID,0,color);
			CPen *oldPen=dc->SelectObject(&pen);
			dc->MoveTo(left+i,y1);
			dc->LineTo(left+i,y2);
			dc->SelectObject(oldPen);
		}
	}
}


int CaplReBar::MaxButtonCount=17;

BEGIN_MESSAGE_MAP(CaplReBar, CReBar)
	//{{AFX_MSG_MAP(CaplToolBar)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
	ON_WM_SIZE()
//	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
//	ON_WM_NCPAINT()
//ON_WM_PAINT()
//ON_WM_PAINT()
ON_NOTIFY_REFLECT(RBN_CHILDSIZE, &CaplReBar::OnRbnChildSize)
END_MESSAGE_MAP()


CaplReBar::CaplReBar()
{
	m_index=-1;
	b_logo_created=false;
	m_logo_bar_width=30;
}

CaplReBar::~CaplReBar()
{
}

void CaplReBar::CreateLogoBar(CBitmap *bkbmp, COLORREF mask)
{
	if(0==bkbmp) return;
	if(b_logo_created) return;
	if(m_LogoBar.m_hWnd!=0) return;

	BITMAP bmp;
	bkbmp->GetBitmap(&bmp);
	if(bmp.bmWidth==0 || bmp.bmHeight==0) return;

	m_il.Create(bmp.bmWidth,bmp.bmHeight,ILC_COLORDDB|ILC_MASK,0,1);
	m_il.Add(bkbmp,mask);

	m_LogoBar.CreateEx(this,TBSTYLE_FLAT|TBSTYLE_TRANSPARENT);

	{
		CaplSetResourceHandle setres(module_inst);
		m_LogoBar.LoadToolBar(IDR_LOGO_TMPL);
	}


	m_LogoBar.SetSizes(CSize(bmp.bmWidth+7, bmp.bmHeight+6),CSize(bmp.bmWidth, bmp.bmHeight));
	m_LogoBar.GetToolBarCtrl().SetImageList(&m_il);		
	AddBar(&m_LogoBar,_T(""),0,RBBS_FIXEDSIZE |RBBS_NOGRIPPER |RBBS_FIXEDBMP|RBBS_CHILDEDGE);


	m_logo_bar_width=bmp.bmWidth+20;
	b_logo_created=true;

	UpdateLogoBarVizible();
}

void CaplReBar::StartAnimation(bool bStart)
{
	return;
	/*{
	if(!b_logo_created) return;

	if(bStart)
	{
		m_index=1;
		m_btn.SetIcon(m_il.ExtractIcon(m_index*2+1),m_il.ExtractIcon(m_index*2));
		m_Timer=SetTimer(123,100,0);
	}
	else
	{
		KillTimer(123);
		m_index=-1;
		m_btn.SetIcon(m_il.ExtractIcon(1),m_il.ExtractIcon(0));
	}*/
}

void CaplReBar::OnTimer(UINT nIDEvent) 
{
	return;
	/*
	if(nIDEvent==123)
	{
		if(m_index!=-1)
		{
			m_index++;
			if(m_index>=MaxButtonCount)m_index=1;
			
			if(b_logo_created)
				m_btn.SetIcon(m_il.ExtractIcon(m_index*2+1),m_il.ExtractIcon(m_index*2));
		}
	}*/
	//else 
		CReBar::OnTimer(nIDEvent);
}

void CaplReBar::SetBitmap(CBitmap *bkbmp)
{
	return;
}

void CaplReBar::UpdateLogoBarVizible()
{
	if(b_logo_created)
	{
		if((int)GetReBarCtrl().GetBandCount()>1)
		{
			CFrameWnd *frm=(CFrameWnd *)AfxGetMainWnd();
			if(frm!=0)
			{
				RECT rect;
				GetWindowRect(&rect);

				REBARBANDINFO rbbi;
				rbbi.cbSize=sizeof(REBARBANDINFO);
				rbbi.fMask=RBBIM_CHILDSIZE|RBBIM_CHILD;
				BOOL b1= GetReBarCtrl().GetBandInfo(0, &rbbi );

				if(rbbi.hwndChild==m_LogoBar.m_hWnd) GetReBarCtrl().GetBandInfo(1, &rbbi );

				if((rect.right-rect.left-m_logo_bar_width-20) > (int) rbbi.cxMinChild)
				{
					int num_visible_band=GetNoLogoBarsCount();
					if(num_visible_band>0)	
						frm->ShowControlBar(&m_LogoBar, TRUE, FALSE);
				}
				else
				{
					frm->ShowControlBar(&m_LogoBar, FALSE, FALSE);
				}
			}
		}
	}
	Invalidate();
}

void CaplReBar::OnSize(UINT nType, int cx, int cy)
{
	CReBar::OnSize(nType, cx, cy);

	// TODO: Add your message handler code here

	UpdateLogoBarVizible();
	//Invalidate();//RedrawWindow();
}

BOOL CaplReBar::OnEraseBkgnd(CDC* pDC)
{
	//return TRUE;
	//return CReBar::OnEraseBkgnd(pDC);
	RECT rect;
	GetWindowRect(&rect);
	ScreenToClient(&rect);
	rect.top=0;

	int rect_width=rect.right-rect.left;
	int rect_heigh=rect.bottom-rect.top;
	
	bool bUseGradient=false;

	if(0!=CaplUIColors::fon_tb.m_hObject && CaplUIColors::bUseGrarient) bUseGradient=true;
	
	CDC memdc; 
	CBitmap *oldBitmap=0;
	BITMAP bmp;

	CaplMemDC tmpDC(pDC);

	CDC *dc=&tmpDC;

	if(bUseGradient &&  CaplUIColors::bUseBitmap)
	{
		memdc.CreateCompatibleDC(pDC);
		oldBitmap=memdc.SelectObject(&CaplUIColors::fon_tb);
		CaplUIColors::fon_tb.GetBitmap(&bmp);
		dc->SetStretchBltMode(HALFTONE);
		//pDC->SetStretchBltMode(HALFTONE);
		//tmpDC.StretchBlt(rect.left,rect.top,rect_width,rect_heigh,&memdc,0,0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
	}
	else
	{
		dc->FillSolidRect(&rect,CaplUIColors::m_color_bk_no_sel);
		//dc->FillSolidRect(&rect,RGB(255,0,0));
	}

	/*int i,y=0,k=GetReBarCtrl().GetRowCount();
	for(i=0;i<k;i++)
	{
		int cy=GetReBarCtrl().GetRowHeight(i);
		if(bUseGradient)
		{
			dc->StretchBlt(rect.left,y,rect_width,cy,&memdc,0,0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
		}
		if(i>0)
		{
			CPen pen1(PS_SOLID,1,GetSysColor(COLOR_3DSHADOW));
			CPen pen2(PS_SOLID,1,GetSysColor(COLOR_3DHIGHLIGHT));
			CPen *oldpen=tmpDC.SelectObject(&pen1);
			dc->MoveTo(rect.left,y-2);
			dc->LineTo(rect.right,y-2);
			dc->SelectObject(&pen2);
			dc->MoveTo(rect.left,y-1);
			dc->LineTo(rect.right,y-1);
			dc->SelectObject(oldpen);
		}
		y+=cy;
		y+=2;
	}*/


	
	
	RECT rect1;
	REBARBANDINFO rbbi;
	rbbi.cbSize=sizeof(REBARBANDINFO);
	rbbi.fMask=RBBIM_CHILDSIZE|RBBIM_SIZE|RBBIM_IDEALSIZE|RBBIM_CHILD;
	rect1.left=2;rect1.right=rect.right-2;
	int i,k,last_y=0;
	k=(int)GetReBarCtrl().GetBandCount();
	for(i=0;i<k;i++)
	{
		RECT rchild;
		GetReBarCtrl().GetRect(i,&rchild);
		if(rchild.bottom<=last_y) continue;
		last_y=rchild.bottom;

		BOOL b1= GetReBarCtrl().GetBandInfo(i, &rbbi );
		if(bUseGradient)
		{
			if(CaplUIColors::bUseBitmap)
			{
				dc->StretchBlt(rect.left,rchild.top,rect_width,rchild.bottom-rchild.top,&memdc,0,0, bmp.bmWidth, bmp.bmHeight,SRCCOPY);
			}
			else
			{
				RECT r; 
				r.left=rect.left; r.right=rect.left+rect_width;
				r.top=rchild.top; r.bottom=rchild.bottom;
				aplDrawGradient(dc,&r,CaplUIColors::m_color_bk_no_sel,CaplUIColors::m_color_gradient,0);
			}
		}

		if(rchild.top < 5) continue;
		rect1.top=rchild.top-1;
		rect1.bottom=rchild.top+1;
		CPen pen1(PS_SOLID,1,GetSysColor(COLOR_3DSHADOW));
		CPen pen2(PS_SOLID,1,GetSysColor(COLOR_3DHIGHLIGHT));
		CPen *oldpen=tmpDC.SelectObject(&pen1);
		dc->MoveTo(rect.left,rchild.top-2);
		dc->LineTo(rect.right,rchild.top-2);
		dc->SelectObject(&pen2);
		dc->MoveTo(rect.left,rchild.top-1);
		dc->LineTo(rect.right,rchild.top-1);
		dc->SelectObject(oldpen);
	}

	if(bUseGradient && CaplUIColors::bUseBitmap) memdc.SelectObject(oldBitmap);

	return TRUE;
}
int CaplReBar::GetNoLogoBarsCount(int *logobar_id)
{
	CFrameWnd *frm=(CFrameWnd *)AfxGetMainWnd();
	if(0==frm) return -1;

	REBARBANDINFO rbbi;
	rbbi.cbSize=sizeof(REBARBANDINFO);
	rbbi.fMask=RBBIM_CHILD;

	int num_visible_band=0;
	int i,k;
	k=GetReBarCtrl().GetBandCount( );
	for(i=0;i<k;i++)
	{
		BOOL b1= GetReBarCtrl().GetBandInfo(i, &rbbi );
		if(!b1) continue;
		HWND hwndChild=rbbi.hwndChild;

		if(hwndChild==m_LogoBar.m_hWnd)
		{
			if(logobar_id!=0) *logobar_id=i;
		}
		else
		{
			CWnd *wnd=CWnd::FromHandle(hwndChild);
			if(wnd!=0)
			{
				if(wnd->IsWindowVisible())num_visible_band++;
			}
		}
	}
	return num_visible_band;
}

void CaplReBar::OnRbnChildSize(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMREBARCHILDSIZE pNMRBCS = reinterpret_cast<LPNMREBARCHILDSIZE>(pNMHDR);
	// TODO: Add your control notification handler code here
	if(0!=pResult) *pResult = 0;

	CFrameWnd *frm=(CFrameWnd *)AfxGetMainWnd();
	if(0==frm) return;

	int logobar_id=-1;

	int num_visible_band=GetNoLogoBarsCount(&logobar_id);
	if(num_visible_band<0 || m_LogoBar.m_hWnd==0) return;

	if(0==num_visible_band && m_LogoBar.IsVisible())
	{
		//Скрываем logobar
		if(logobar_id>=0)
		{
			GetReBarCtrl().ShowBand(logobar_id,FALSE);
		}
		else frm->ShowControlBar(&m_LogoBar, FALSE, FALSE);
		//Invalidate();
	}
	else if(num_visible_band>0 && (!m_LogoBar.IsVisible())  && b_logo_created )
	{
		//показываем logobar
		if(logobar_id>=0)
		{
			GetReBarCtrl().ShowBand(logobar_id,TRUE);
		}
		else frm->ShowControlBar(&m_LogoBar, TRUE, TRUE);
	}
}
