// GanttView.cpp : implementation file
//

#include "stdafx.h"
#include "resource.h"
#include "WfGanttView.h"

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

/////////////////////////////////////////////////////////////////////////////
// CWfGanttView

IMPLEMENT_DYNCREATE(CWfGanttView, CView)

CWfGanttView::CWfGanttView()
{
	m_tree_view=0;
	m_TLInitialized=FALSE;
	m_bShrinkToFit=true;
}

CWfGanttView::~CWfGanttView()
{
}


BEGIN_MESSAGE_MAP(CWfGanttView, CView)
	//{{AFX_MSG_MAP(CWfGanttView)
	ON_WM_MOUSEACTIVATE()
	ON_WM_SIZE()
	ON_WM_HSCROLL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWfGanttView drawing

void CWfGanttView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CWfGanttView diagnostics

#ifdef _DEBUG
void CWfGanttView::AssertValid() const
{
	CView::AssertValid();
}

void CWfGanttView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CWfGanttView message handlers

void CWfGanttView::Initialize()
{
	CRect m_wndRect;
	GetWindowRect(&m_wndRect);
	CRect m_ganttRect;

	// create the ctrl itself
	{
		GetWindowRect(&m_wndRect);

		m_ganttRect.left=0;
		//m_ganttRect.top = m_gantt.m_headerHeight+1;
		m_ganttRect.top = 1;;
		m_ganttRect.right = m_wndRect.Width()-5;
		m_ganttRect.bottom = m_wndRect.Height()-GetSystemMetrics(SM_CYHSCROLL)-4;

		m_gantt.Create(NULL,NULL,WS_CHILD | WS_VISIBLE ,m_ganttRect, this, ID_GANTT_CTRL);
		
		//m_gantt.m_tooltip.Create(&m_gantt);
		//m_gantt.m_tooltip.Activate(TRUE);
		//m_gantt.m_tooltip.AddTool(&m_gantt,_T("whatever"),m_ganttRect,1);
	/*	m_gantt.m_tooltip.Create(this);
		m_gantt.m_tooltip.Activate(TRUE);
		m_gantt.m_tooltip.AddTool(this,_T("whatever"),m_ganttRect,1);*/
	}
	// finally, create the horizontal scroll bar
	{
		CRect m_scrollRect;
		m_scrollRect.left=0;
		m_scrollRect.top = m_ganttRect.bottom;
		m_scrollRect.right = m_ganttRect.Width()-GetSystemMetrics(SM_CXVSCROLL);
		m_scrollRect.bottom = m_wndRect.bottom;

		m_horScrollBar.Create(WS_CHILD | WS_VISIBLE | WS_DISABLED | SBS_HORZ | SBS_TOPALIGN, m_scrollRect, this, ID_GANTT_SCROLLBAR);
	}

}

void CWfGanttView::OnInitialUpdate() 
{
	CView::OnInitialUpdate();
	
	// TODO: Add your specialized code here and/or call the base class
	Initialize();	

	//m_gantt.SetImageList(&m_cImageList, TVSIL_NORMAL);

	CRect m_wndRect;
	GetClientRect(&m_wndRect);
	MoveWindow(0, 0, m_wndRect.Width(), m_wndRect.Height());
	m_TLInitialized = TRUE;	
}

int CWfGanttView::OnMouseActivate( CWnd* pDesktopWnd, 
                                  UINT nHitTest, 
                                  UINT message )
{
  return MA_ACTIVATE;
}

void CWfGanttView::Update(bool bUpdateCalendar)
{
	CString old_max_date,new_max_date;
	m_gantt.GetMaxDate(old_max_date);
	CString old_min_date,new_min_date;
	m_gantt.GetMinDate(old_min_date);
	int old_pix_in_day=m_gantt.GetPixelsInDay();
	int old_dlit=m_gantt.GetDlitDays(old_min_date,old_max_date);
	int m_nCurPos = m_horScrollBar.GetScrollPos();
	int old_min_pos,old_max_pos;
	m_horScrollBar.GetScrollRange(&old_min_pos,&old_max_pos);
	if(bUpdateCalendar) m_gantt.UpdateCalendar();
	if(m_tree_view)
	{
		HTREEITEM hRoot=m_tree_view->m_tree.GetRootItem();
		CRect rect;
		if(hRoot) 
		{
			m_tree_view->m_tree.GetItemRect(hRoot,rect,false);
			m_gantt.m_blockHeight= rect.Height();
		}
	}
	m_gantt.GetMaxDate(new_max_date);
	m_gantt.GetMinDate(new_min_date);
	bool bNeedScroll=false;
	if(old_max_date!=new_max_date || old_min_date!=new_min_date) 
	{
		ResetScrollBar();
		bNeedScroll=true;
		if(m_bShrinkToFit) m_gantt.AutoResizeDiagram(false,false);
	}
	if(bNeedScroll)
	{
		int new_min_pos,new_max_pos;
		m_horScrollBar.GetScrollRange(&new_min_pos,&new_max_pos);
		int new_pix_in_day=m_gantt.GetPixelsInDay();
		int new_min_date_delta=m_gantt.GetDlitDays(old_min_date,new_min_date);
		int scrolling_day=(int)m_nCurPos/old_pix_in_day;
		m_nCurPos=scrolling_day*new_pix_in_day-new_min_date_delta*new_pix_in_day;
		if(m_nCurPos>new_max_pos) m_nCurPos=new_max_pos;
		if(m_nCurPos<new_min_pos) m_nCurPos=new_min_pos;
		m_gantt.m_nOffset = -m_nCurPos;
		m_horScrollBar.SetScrollPos(m_nCurPos);
		CRect m_scrollRect;
		m_gantt.GetClientRect(&m_scrollRect);
		m_gantt.ScrollWindow(m_nCurPos, 0, &m_scrollRect, &m_scrollRect);
	}
	
	Invalidate();
}

BOOL CWfGanttView::VerticalScrollVisible()
{	
	int sMin, sMax;
	m_gantt.GetScrollRange(SB_VERT, &sMin, &sMax);	
	return sMax!=0;
}

BOOL CWfGanttView::HorizontalScrollVisible()
{
	int sMin, sMax;
	m_horScrollBar.GetScrollRange(&sMin, &sMax);
	return sMax!=0;
}

int CWfGanttView::StretchWidth(int m_nWidth, int m_nMeasure)
{	
	return ((m_nWidth/m_nMeasure)+1)*m_nMeasure;//put the fixed for +1 in brackets f/0 error
}


void CWfGanttView::ResetScrollBar()
{
	// resetting the horizontal scroll bar

	int m_nTotalWidth=0, m_nPageWidth;

	CRect m_ganttRect;
	m_gantt.GetClientRect(&m_ganttRect);

	CRect m_wndRect;
	GetClientRect(&m_wndRect);

/*	CRect m_headerRect;
	m_gantt.m_wndHeader.GetClientRect(&m_headerRect);*/

	CRect m_barRect;
	m_horScrollBar.GetClientRect(m_barRect);

	m_nPageWidth = m_ganttRect.Width();

	m_nTotalWidth = m_gantt.GetColumnsWidth();

	if(m_nTotalWidth > m_nPageWidth)
	{
		// show the scroll bar and adjust it's size
		{
			m_horScrollBar.EnableWindow(TRUE);

			m_horScrollBar.ShowWindow(SW_SHOW);

			// the tree becomes smaller
			//m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height()-m_gantt.m_headerHeight, SWP_NOMOVE);
			m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height(), SWP_NOMOVE);

			if(!VerticalScrollVisible())
				// i.e. vertical scroll bar isn't visible
			{
				m_horScrollBar.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_barRect.Height(), SWP_NOMOVE);
			}
			else
			{
				m_horScrollBar.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width() - GetSystemMetrics(SM_CXVSCROLL), m_barRect.Height(), SWP_NOMOVE);
			}
		}

		m_horScrollBar.SetScrollRange(0, m_nTotalWidth-m_nPageWidth);

		// recalculate the offset
		{
		/*	CRect m_wndHeaderRect;
			m_gantt.m_wndHeader.GetWindowRect(&m_wndHeaderRect);
			ScreenToClient(&m_wndHeaderRect);

			m_gantt.m_nOffset = m_wndHeaderRect.left;
			m_horScrollBar.SetScrollPos(-m_gantt.m_nOffset);*/
			m_gantt.m_nOffset = 0;
			m_horScrollBar.SetScrollPos(0);
		}
	}
	else
	{
		m_horScrollBar.EnableWindow(FALSE);

		// we no longer need it, so hide it!
		{
			m_horScrollBar.ShowWindow(SW_HIDE);

			//m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height() - m_gantt.m_headerHeight, SWP_NOMOVE);
			m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height(), SWP_NOMOVE);
			// the tree takes scroll's place
		}

		m_horScrollBar.SetScrollRange(0, 0);

		// set scroll offset to zero
		{
			m_gantt.m_nOffset = 0;
			m_gantt.Invalidate();
/*			CRect m_headerRect;
			m_gantt.m_wndHeader.GetWindowRect(&m_headerRect);*/
			CRect m_wndRect;
			GetClientRect(&m_wndRect);
		//	m_gantt.m_wndHeader.SetWindowPos(&wndTop, m_gantt.m_nOffset, 0, max(StretchWidth(m_gantt.GetColumnsWidth(),m_wndRect.Width()),m_wndRect.Width()), m_headerRect.Height(), SWP_SHOWWINDOW);
			
		}
	}
}





void CWfGanttView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	
	SetScrollRange(SB_HORZ, 0, 0);
	SetScrollRange(SB_VERT, 0, 0);

	if(m_TLInitialized)
	{	
		// resize all the controls	
		CRect m_wndRect;
		GetClientRect(&m_wndRect);

		CRect m_scrollRect;
		m_horScrollBar.GetClientRect(&m_scrollRect);

		m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height() - m_scrollRect.Height(), SWP_NOMOVE);

		CRect m_ganttRect;
		m_gantt.GetClientRect(&m_ganttRect);
		m_horScrollBar.MoveWindow(0, m_ganttRect.bottom, m_wndRect.Width(), m_scrollRect.Height());

		if(m_gantt.GetColumnsWidth() > m_ganttRect.Width())
		{
			// show the horz scroll bar
			{
				CRect m_barRect;
				m_horScrollBar.GetClientRect(&m_barRect);			

				m_horScrollBar.EnableWindow(TRUE);

				m_horScrollBar.ShowWindow(SW_SHOW);

				// the tree becomes smaller
				m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height()-m_barRect.Height(), SWP_NOMOVE);

				int tfdsfsd=m_wndRect.Width() - GetSystemMetrics(SM_CXVSCROLL);
				m_horScrollBar.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width() - GetSystemMetrics(SM_CXVSCROLL), m_barRect.Height(), SWP_NOMOVE);
				
			}

			m_horScrollBar.SetScrollRange(0, m_gantt.GetColumnsWidth()-m_ganttRect.Width());

		}
		else
		{
			// hide the scroll bar
			{
				m_horScrollBar.EnableWindow(FALSE);

				m_horScrollBar.ShowWindow(SW_HIDE);

				// the tree becomes larger
				m_gantt.SetWindowPos(&wndTop, 0, 0, m_wndRect.Width(), m_wndRect.Height(), SWP_NOMOVE);				
			}

			m_horScrollBar.SetScrollRange(0, 0);
		}

		m_gantt.ResetVertScrollBar();
		
		// Reset the header control position and scroll
		// the tree control as required.
		int m_nCurPos = m_horScrollBar.GetScrollPos();
		m_gantt.m_nOffset = -m_nCurPos;
	
		// smoothly scroll the tree control
	    {
		CRect m_scrollRect;
		m_gantt.GetClientRect(&m_scrollRect);
		m_gantt.ScrollWindow(m_nCurPos, 0, &m_scrollRect, &m_scrollRect);
		}
		
		GetClientRect(&m_wndRect);

		if(m_bShrinkToFit) m_gantt.AutoResizeDiagram();
	}	
}

void CWfGanttView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	CRect m_ganttRect;
	m_gantt.GetClientRect(&m_ganttRect);
	
	// if horizontal scroll bar 
	if(pScrollBar == &m_horScrollBar)
	{
		int m_nCurPos = m_horScrollBar.GetScrollPos();
		int m_nPrevPos = m_nCurPos;
		// decide what to do for each diffrent scroll event
		switch(nSBCode)
		{
			case SB_LEFT:			m_nCurPos = 0;
									break;
			case SB_RIGHT:			m_nCurPos = m_horScrollBar.GetScrollLimit()-1;
									break;
			case SB_LINELEFT:		m_nCurPos = max(m_nCurPos-6, 0);
									break;
			case SB_LINERIGHT:		m_nCurPos = min(m_nCurPos+6, m_horScrollBar.GetScrollLimit()-1);
									break;
			case SB_PAGELEFT:		m_nCurPos = max(m_nCurPos-m_ganttRect.Width(), 0);
									break;
			case SB_PAGERIGHT:		m_nCurPos = min(m_nCurPos+m_ganttRect.Width(), m_horScrollBar.GetScrollLimit()-1);
									break;
			case SB_THUMBTRACK:
			case SB_THUMBPOSITION:  if(nPos==0)
									    m_nCurPos = 0;
								    else
									    m_nCurPos = min(StretchWidth(nPos, 6), m_horScrollBar.GetScrollLimit()-1);
								    break;
		}		

		m_horScrollBar.SetScrollPos(m_nCurPos);
		m_gantt.m_nOffset = -m_nCurPos;

		// smoothly scroll the control
		{
			CRect m_scrollRect;
			m_gantt.GetClientRect(&m_scrollRect);
			m_gantt.ScrollWindow(m_nPrevPos - m_nCurPos, 0, &m_scrollRect, &m_scrollRect);
		}

		Invalidate();
	}	
	CView::OnHScroll(nSBCode, nPos, pScrollBar);
}

bool CWfGanttView::ZoomIn(int step)
{
	int pixelsInDay=m_gantt.GetPixelsInDay();
	if(0!=step) return m_gantt.SetPixelsInDay(pixelsInDay+step);
	
	pixelsInDay=(int)(pixelsInDay*1.4) +1 ;
	return m_gantt.SetPixelsInDay(pixelsInDay);
}

bool CWfGanttView::ZoomOut(int step)
{
	int pixelsInDay=m_gantt.GetPixelsInDay();
	if(0!=step) return m_gantt.SetPixelsInDay(pixelsInDay-step);

	pixelsInDay=(int)(pixelsInDay*10/14);	
	return m_gantt.SetPixelsInDay(pixelsInDay);
}



