#include "stdafx.h"
#include "INKS.h"
#include "MainFrm.h"
#include "INKSDoc.h"
#include "INKSView.h"
#include "Resource.h"

#include "MouseTracker.h"
#include <afxpriv.h>
#include "Wire.h"
#include "Tag.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CMouseTracker::CMouseTracker(CWnd *pWnd, CMouseSnap *SnapMouse) 
	: m_pWnd(pWnd), m_Point(0), m_PointStart(0), m_PointPrevious(0), pDC(0), m_Mode(ModeSelect), m_CursorMode(HandleNothing), m_CreateMode(NoCreate), m_SnapMouse(SnapMouse), m_gAddWireObject(NULL), m_bSelectRegion(false), m_bEditWire(false), m_nSOListCount(0), m_nCOListCount(0), m_bMoveCObject(false), m_pGPath(NULL), m_pSpaceHash(NULL), m_pPriorQueue(NULL), m_pRoot(NULL), m_oldWirePoints(NULL), m_nOldPointCount(0), m_pView(NULL), m_nEditEdgeWirePoint(-1)
{
	m_pBrush = new SolidBrush(Color(40, 40,50,100));
	m_pPen = new Pen(Color(50,50,50), 0.25);
	m_nWireConnection[0] = 0;
	m_nWireConnection[1] = 0;
	ASSERT_VALID(pWnd);
}

CMouseTracker::~CMouseTracker()
{
	SAFE_DELETE(m_pPriorQueue);
	SAFE_DELETE_ARRAY(m_pGPath);
	SAFE_DELETE_ARRAY(m_oldWirePoints);
}
void CMouseTracker::InitialUpdate(CINKSView *pView)
{
	m_pView = pView;
	m_pSOList = m_pView->GetSOList();
}

void CMouseTracker::Reset()
{
	m_Point = 0;
	m_PointStart = 0;
	m_PointPrevious = 0;
	SAFE_DELETE_ARRAY(m_gAddWireObject);
	m_nWireConnection[0] = 0;
	m_nWireConnection[1] = 0;
	Anchors.RemoveAll();
	m_bSelectRegion = false;
	m_bEditWire = false;
	m_nEditEdgeWirePoint = -1;
	m_bMoveCObject = false;
	m_nSOListCount = 0;
	m_nCOListCount = 0;
	m_rectSelectedRegion.SetRectEmpty();
	m_Transform.Reset();
	SAFE_DELETE_ARRAY(m_oldWirePoints);
	m_nOldPointCount = 0;
	SAFE_DELETE_ARRAY(m_pGPath);
	SAFE_DELETE(m_pPriorQueue);
	SAFE_DELETE(m_pRoot);
}

int CMouseTracker::Track(CDC *pDC, UINT nFlags, CPoint point)
{
	
	if(::GetCapture()){
		TRACE("Track() failed!\n");
		return TrackFailed;
	}
	this->pDC = pDC;
	
	if(m_Mode == ModeCreate && (m_CreateMode == CreateGate || m_CreateMode == CreateBlock || m_CreateMode == CreateInv))
		return TrackCreateNew;

	CPoint pnt = point;

	m_Point = pnt;
	m_PointPrevious = m_Point;
	m_PointStart = m_Point;
	nFlags &= UpdateMouseFlags;

	::AfxLockTempMaps();

	int oldROP2(R2_COPYPEN);
	COLORREF oldBkColor(RGB(0, 0, 0));

	if(pDC != NULL){
		oldROP2 = pDC->SetROP2(R2_NOTXORPEN);
		oldBkColor = pDC->SetBkColor(RGB(255, 255, 255));
	}
	OnUpdate(pDC, nFlags | UpdateFirst);
	
	m_pWnd->SetCapture();
	ASSERT(CWnd::GetCapture() == m_pWnd);

	int r = OnBeginTrack(nFlags, point);
	if(r != TrackContinue){
		VERIFY(::ReleaseCapture());
		::AfxUnlockTempMaps();
		return r;
	}

	ASSERT(r == TrackContinue);
	while(r == TrackContinue){
		MSG msg;

		int cnt = 0;
		while(!::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
			// Give the statusbar the opportunity to update itself
			// by sending a private MFC message (see <afxpriv.h>).
			if(cnt == 0)
				::AfxGetMainWnd()->SendMessageToDescendants(WM_IDLEUPDATECMDUI, TRUE);
			cnt++;
		}

		if(CWnd::GetCapture() != m_pWnd || msg.message == WM_CANCELMODE)
			r = TrackFailed;

		else if(msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST){

			int x = (int)(short) LOWORD(msg.lParam);
			int y = (int)(short) HIWORD(msg.lParam);

			((CINKSView*)m_pView)->OnPrepareDC(pDC);
			((CINKSView*)m_pView)->SetMapMode(pDC);
			CPoint pnt(x, y);
			((CINKSView*)m_pView)->DPtoLP(&pnt);
			m_SnapMouse->SnapCursor(pnt);
			//TRACE2("MT - mouse X:%d Y:%d\n", pnt.x, pnt.y);
			
			m_Point = pnt;
			nFlags = (UINT) msg.wParam & UpdateMouseFlags;
			r = OnMouseMessage(msg, nFlags, pnt, pDC);
		}

		else if(msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST){
			r = OnKeybMessage(msg, (UINT)msg.wParam, (UINT)LOWORD(msg.lParam), (UINT)HIWORD(msg.lParam));
		}

		else r = OnMessage(msg);
	}

	VERIFY(::ReleaseCapture());
	::AfxUnlockTempMaps();
	r = OnEndTrack(r);
	if (pDC != NULL){
		// Clean up pDC
		pDC->SetROP2(oldROP2);
		pDC->SetBkColor(oldBkColor);
	}
	return r;
}

void CMouseTracker::Draw(CDC *pDC, Graphics &g)
{
	int nCount = 0;
	CCommonObject *pObject = NULL;
	POSITION pos = m_pSOList->GetHeadPosition();
	while(pos){
		pObject = m_pSOList->GetNext(pos);
		if(pObject){
			if(pObject->GetType() != 4)
				g.FillPath(m_pBrush, pObject->m_gPath);
			else{
				((CWire*)pObject)->DrawAnchors(pDC);
			}
			Rect rect;
			for(int i=0; i<pObject->m_nIn; i++){
				rect.X = pObject->m_Connection.m_rectIns[i].left;
				rect.Y = pObject->m_Connection.m_rectIns[i].top;
				rect.Width = pObject->m_Connection.m_rectIns[i].Width();
				rect.Height = pObject->m_Connection.m_rectIns[i].Height();
				g.DrawRectangle(m_pPen, rect);
				g.FillRectangle(m_pBrush, rect);
			}
			for(int i=0; i<pObject->m_nOut; i++){
				rect.X = pObject->m_Connection.m_rectOuts[i].left;
				rect.Y = pObject->m_Connection.m_rectOuts[i].top;
				rect.Width = pObject->m_Connection.m_rectOuts[i].Width();
				rect.Height = pObject->m_Connection.m_rectOuts[i].Height();
				g.DrawRectangle(m_pPen, rect);
				g.FillRectangle(m_pBrush, rect);
			}
			nCount++;
		}
	}
}

int CMouseTracker::OnBeginTrack(UINT nFlags, CPoint point)
{
	if(m_Mode == ModeCreate && m_CreateMode == CreateWire){
		m_gAddWireObject = new CCommonObject*[2];
		m_gAddWireObject[0] = ConnectHitTest(point, m_nWireConnection[0]);
		if(m_nWireConnection[0]){ // we hit in or out port of ccommonobj (numb<0 || > numb>0)
			int i = m_nWireConnection[0];
			if(i > 0){ // we hit in port
				CPoint cpoint;
				if(m_gAddWireObject[0]->m_nObjType != 4)
					cpoint = m_gAddWireObject[0]->m_Connection.m_rectIns[i-1].CenterPoint();
				else{
					cpoint = point;
					m_SnapMouse->SnapCursor(cpoint);
				}
				
				m_gAddWireObject[0]->m_Connection.m_rectIns[0];
				Anchors.AddTail(Anchor(cpoint));
			}
			else if(i < 0){ // we hit out port
				CPoint cpoint = m_gAddWireObject[0]->m_Connection.m_rectOuts[abs(i)-1].CenterPoint();
				m_gAddWireObject[0]->m_Connection.m_rectOuts[0];
				Anchors.AddTail(Anchor(cpoint));;
			}
			return TrackContinue;
		}
	}
	else if(m_Mode == ModeSelect || m_Mode == ModeZoomIn || m_Mode == ModeZoomOut){
		// going to edit wire
		if(m_nSOListCount == 1 && this->m_pSOList->GetHead()->m_nObjType == 4 && !m_bSelectRegion){
			m_bEditWire = true;
			CWire *pTemp = ((CWire*)m_pSOList->GetHead());
			int nEditEdge = 0;
			nEditEdge = pTemp->EditEdgePoint(point);
			if(nEditEdge > 0){ // going to edit head || tail of wire
				m_nEditEdgeWirePoint = nEditEdge;
				pTemp->PrepareForEditEdge(nEditEdge);
				m_nOldPointCount = (int)pTemp->m_gPath->GetPointCount();
				m_oldWirePoints = new Point[m_nOldPointCount];
				pTemp->m_gPath->GetPathPoints(m_oldWirePoints, m_nOldPointCount);
			}
			else{ // going to edit part of wire
				CPoint cpoint = point;
				//m_SnapMouse->SnapCursor(cpoint);
				pTemp->PrepareForEdit(cpoint);
				m_nOldPointCount = (int)pTemp->m_gPath->GetPointCount();
				m_oldWirePoints = new Point[m_nOldPointCount];
				pTemp->m_gPath->GetPathPoints(m_oldWirePoints, m_nOldPointCount);
			}
		}
		else if(m_bMoveCObject){
			m_pGPath = new GraphicsPath*[m_nSOListCount];
			//m_SOListIterator->ToFront();
			int i=0;
			//// create bounding rectangles used as draft of selected objects
			POSITION pos = m_pSOList->GetHeadPosition();
			while(pos){
				m_pGPath[i++] = m_pSOList->GetNext(pos)->m_gPath->Clone();
			}
		}
		return TrackContinue;
	}
	else if(m_Mode == ModeCreate && m_CreateMode == CreateTag){
		// create bounding rectangle used as draft for creating tag
		
		// create storage for object that is about to be tagged
		m_gAddWireObject = new CCommonObject*[1];
		
		return TrackContinue;
	}
	else if(m_Mode == ModeZoomHand)
		return TrackContinue;
	return TrackCancelled;
}

int CMouseTracker::OnEndTrack(int trackResult)
{
	bool bEditWireEdge = false;
	if(trackResult == TrackMove){
		if(m_PointStart == m_Point)
			return TrackCancelled;
	}
	if(trackResult != TrackNoMove){
	if(m_bEditWire){
		if(m_pSOList->GetSize()){
			CWire *pTemp = ((CWire*)this->m_pSOList->GetHead());
			//Point **newPoints = new Point*[2];
			if(this->m_nEditEdgeWirePoint < 0){
				pTemp->FinishWireEdit();
			}
			else{
				pTemp->FinishWireEdgeEdit();
				bEditWireEdge = true;
			}
			int nNewPointCount = (int)pTemp->m_gPath->GetPointCount();
			Point *pNewPoints = new Point[nNewPointCount];
			pTemp->m_gPath->GetPathPoints(pNewPoints, nNewPointCount);
			m_pSpaceHash->MoveWire(pTemp, m_oldWirePoints, m_nOldPointCount, pNewPoints, nNewPointCount);
			SAFE_DELETE_ARRAY(pNewPoints);
		}
		//((CWire*)m_SOListIterator->PeekFirst())->FinishWireEdit();
	}
	if(m_bMoveCObject && trackResult != TrackNoMove && !m_bEditWire){
		CCommonObject *pObj = NULL;
		POSITION pos = m_pSOList->GetHeadPosition();
		int i = 0;
		while(pos){
			pObj = m_pSOList->GetNext(pos);
			if(pObj->m_nObjType == 4){
				int nPointCount = pObj->m_gPath->GetPointCount();
				Point* oldPoints = new Point[nPointCount];
				pObj->m_gPath->GetPathPoints(oldPoints, nPointCount);
				Point* newPoints = new Point[nPointCount];
				pObj->TransformCObject(&m_Transform);
				pObj->m_gPath->GetPathPoints(newPoints, nPointCount);
				m_pSpaceHash->MoveWire(pObj, oldPoints, nPointCount, newPoints, nPointCount);
			}
			else{
				if(m_pSpaceHash->CanMoveCObject(m_pGPath[i])){
					CPoint oldTL(pObj->GetBounds()->X, pObj->GetBounds()->Y);
					pObj->TransformCObject(&m_Transform);
					m_pSpaceHash->MoveCObject(pObj, oldTL);

					int nIns = pObj->m_nIn;
					int nOuts = pObj->m_nOut;

					CCommonObject *pTemp = NULL;
					for(int i=0; i<nIns; i++){
						pTemp = pObj->m_Connection.m_pObjectIn[i];
						if(pTemp && pTemp->GetType() == 5){ // CTag attached to input of this object
							CPoint oldTL(pTemp->GetBounds()->X, pTemp->GetBounds()->Y);
							((CTag*)(pObj->m_Connection.m_pObjectIn[i]))->SetParentMove(true);
							pObj->m_Connection.m_pObjectIn[i]->TransformCObject(&m_Transform);
							((CTag*)(pObj->m_Connection.m_pObjectIn[i]))->SetParentMove(false);
							m_pSpaceHash->MoveCObject(pTemp, oldTL);
						}
					}

					for(int i=0; i<nOuts; i++){
						pTemp = pObj->m_Connection.m_pObjectOut[i];
						if(pTemp && pTemp->GetType() == 5){ // CTag attached to output of this object
							CPoint oldTL(pTemp->GetBounds()->X, pTemp->GetBounds()->Y);
							((CTag*)(pObj->m_Connection.m_pObjectOut[i]))->SetParentMove(true);
							pObj->m_Connection.m_pObjectOut[i]->TransformCObject(&m_Transform);
							((CTag*)(pObj->m_Connection.m_pObjectOut[i]))->SetParentMove(false);
							m_pSpaceHash->MoveCObject(pTemp, oldTL);
						}
					}
				}
			}
		}
		SAFE_DELETE_ARRAY(m_pGPath);
	}
	if(bEditWireEdge)
		return TrackEditWireEdge;
	}
	return trackResult;
}

CCommonObject* CMouseTracker::ConnectHitTest(CPoint point, int &nNumber)
{
	//m_gObjectsListIterator->ToFront();
	CList<CCommonObject*, CCommonObject*> *pList = m_pView->GetCOList();
	//POSITION pos = m_pSOList->GetHeadPosition();
	CCommonObject *ret = NULL;
	//while(pos){
	//	ret = m_pSOList->GetNext(pos);
	//	if(ret->ConnectHitTest(point, nNumber))
	//		return ret;
	//}
	POSITION pos = pList->GetHeadPosition();
	while(pos){
		ret = pList->GetNext(pos);
		if(ret->ConnectHitTest(point, nNumber))
			return ret;
	}

	return NULL;
}

int CMouseTracker::OnMouseMessage(MSG &msg, UINT nFlags, CPoint point, CDC *pDC)
{
	if(msg.message == WM_LBUTTONDOWN)
		return OnLButtonDown(nFlags, point);

	if(msg.message == WM_LBUTTONUP){
		return OnLButtonUp(nFlags, point);
	}

	if(msg.message == WM_RBUTTONDOWN){
		return OnRButtonDown(nFlags, point);
	}
	if(msg.message == WM_MOUSEMOVE)
		return OnMouseMove(nFlags, point);

	return TrackContinue;
}

int CMouseTracker::OnMouseMove(UINT nFlags, CPoint point)
{

	CPoint p1, p2, p3;
	p1 = p2 = p3 = point;
	m_SnapMouse->SnapCursor(p2);
	theApp->m_pMainFrame->UpdateMousePos(p1, p2, p3);

	//CSize sieze = pDC->GetViewportExt();
	m_Point = point;
	if(m_PointPrevious.x == point.x && m_PointPrevious.y == point.y)
		return TrackContinue;

	// editing wire (edge point || part of wire)
	if(m_Mode == ModeSelect && !m_bSelectRegion){
		if(m_bEditWire){
			if(m_nEditEdgeWirePoint < 0){
				// edit part of wire
				OnUpdate(pDC, UpdateEditWire);
				((CWire*)m_pSOList->GetHead())->MoveAnchorPair(point);
				OnUpdate(pDC, UpdateEditWire);
			}
			else{
				// edit edge points of wire
				OnUpdate(pDC, UpdateEditWireEdge);
				((CWire*)m_pSOList->GetHead())->MoveAnchorEdge(point);
				OnUpdate(pDC, UpdateEditWireEdge);
			}
		}
		else if(m_bMoveCObject){
			//m_SOListIterator->ToFront();
			// NOTXOR drawing ....
			CSize sz = point - m_PointStart;
			CSize deltasize = point - m_PointPrevious;
			OnUpdate(pDC, UpdateMoveGObject);
			sz = point - m_PointPrevious;
			m_Translate.Reset();
			m_Translate.Translate((REAL)deltasize.cx, (REAL)deltasize.cy);
			m_Transform.Translate((REAL)deltasize.cx, (REAL)deltasize.cy);
			for(int i=0; i<m_nSOListCount; i++){
				m_pGPath[i]->Transform(&m_Translate);
			}
			OnUpdate(pDC, UpdateMoveGObject);
		}

		m_PointPrevious = point;
	}
	//drawing wire
	else if(m_Mode == ModeCreate && m_CreateMode == CreateWire){
		pDC->MoveTo(m_PointStart);
		pDC->LineTo(m_PointPrevious);
		pDC->MoveTo(m_PointStart);
		pDC->LineTo(point);
	}

	//selecting multiple objects || selecting rectangle to zoom
	else if((m_Mode == ModeSelect || m_Mode == ModeZoomIn) && m_bSelectRegion){
			SelectMultiple(point);
	}
	else if(m_Mode == ModeSelect && m_bEditWire){
	}
	else if(m_Mode == ModeCreate && m_CreateMode == CreateTag){
		DrawTag(pDC, m_PointPrevious);
		DrawTag(pDC, point);
	}
	else if(m_Mode == ModeZoomHand){
		TRACE2("point x:%d y:%d\n", point.x, point.y);
		OnHandScroll(p2);
	}
	m_PointPrevious = point;
	return TrackContinue;
}

int CMouseTracker::OnLButtonDown(UINT nFlags, CPoint point)
{
	if(m_Mode == ModeCreate && m_CreateMode == CreateWire){
		//Point add(point.x, point.y);
		CCommonObject *pObj = m_pSpaceHash->HashTest(point);
		m_gAddWireObject[1] = ConnectHitTest(point, m_nWireConnection[1]);
		if(pObj && !m_nWireConnection[1])
			return TrackContinue;
		CPoint pnt = Anchors.GetTail().m_PointMain;
		bool bAdapted = AdaptWire(pnt, point, Anchors);
		if(m_nWireConnection[1] && Anchors.GetTail() == point){
			return TrackSucceeded;
		}
		m_PointStart = point;
		m_PointPrevious = point;
		if(!bAdapted){
			m_PointStart = Anchors.GetTail().m_PointMain;
			m_PointPrevious = Anchors.GetTail().m_PointMain;
			return TrackContinue;
		}
	}
	else if(m_Mode == ModeCreate && m_CreateMode == CreateTag){
		this->m_Point = point;
		m_gAddWireObject[0] = ConnectHitTest(point, m_nWireConnection[0]);
		if(m_gAddWireObject[0])
			return TrackSucceeded;
		else
			return TrackContinue;
	}

	return TrackContinue;
}

int CMouseTracker::OnLButtonUp(UINT nFlags, CPoint point)
{
	if(m_PointStart == point && m_Mode != ModeCreate)
		return TrackNoMove;
	if(m_Mode == ModeSelect && !m_bSelectRegion)
		return TrackMove;
	else if((m_Mode == ModeSelect || m_Mode == ModeZoomIn) && m_bSelectRegion){
		m_rectSelectedRegion.SetRect(m_PointStart, point);
		return TrackSelectRegion;
	}
	else if(m_Mode == ModeZoomHand)
		return TrackSucceeded;
	return TrackContinue;
}


int CMouseTracker::OnRButtonDown(UINT nFlags, CPoint point)
{
	if(::GetKeyState(VK_LBUTTON) < 0)
		return TrackContinue;
	if(m_CreateMode == CreateTag){
		this->DrawTag(pDC, point);
		return TrackCancelled;
	}
	else if(m_CreateMode == CreateWire){
		pDC->MoveTo(m_PointStart);
		pDC->LineTo(point);
		return TrackSucceeded;
	}
	return TrackContinue;
}

int CMouseTracker::OnKeybMessage(MSG &msg, UINT nChar, UINT nRepCount, UINT nFlags)
{
	if(msg.message == WM_KEYDOWN && nChar == VK_ESCAPE)
		return TrackCancelled;
	if(m_CursorMode != HandleNothing){
		bool shift = ::GetKeyState(VK_SHIFT) < 0;
		if(shift)	
			m_CursorMode = CursorCopy;
		else m_CursorMode = CursorMove;

	theApp->m_pMainFrame->SetCursor(m_CursorMode);
	}
	return TrackContinue;
}

void CMouseTracker::OnKeyDown(UINT nChar, UINT nRepCount, UINT nFlags)
{
}

void CMouseTracker::OnKeyUp(UINT nChar, UINT nRepCount, UINT nFlags)
{
}

int CMouseTracker::OnMessage(MSG &msg)
{
	::DispatchMessage(&msg);
	return TrackContinue;
}

void CMouseTracker::SelectMultiple(CPoint point)
{
	pDC->Rectangle(m_PointStart.x, m_PointStart.y, m_PointPrevious.x, m_PointPrevious.y);
	pDC->Rectangle(m_PointStart.x, m_PointStart.y, point.x, point.y);
}

void CMouseTracker::OnUpdate(CDC *pDC, UINT nMode)
{
	Graphics g(pDC->GetSafeHdc());
	g.SetSmoothingMode(SmoothingModeHighQuality);
	g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
	g.SetPixelOffsetMode(PixelOffsetModeHighQuality);

	if(nMode & UpdateMoveGObject){	// moving gobject -> redraw draft
		Rect boundRect;
		RECT Rect;
		for(int i=0; i<m_nSOListCount; i++){
			m_pGPath[i]->GetBounds(&boundRect);
			Rect.bottom = boundRect.GetBottom();
			Rect.top = boundRect.GetTop();
			Rect.left = boundRect.GetLeft();
			Rect.right = boundRect.GetRight();
			pDC->Rectangle(&Rect);
		}
	}
	else if(nMode & UpdateEditWire){ // editing wire
		((CWire*)m_pSOList->GetHead())->DrawMovedLine(pDC);
	}
	else if(nMode & UpdateEditWireEdge){ // editing wire
		((CWire*)m_pSOList->GetHead())->DrawMovedEdge(pDC);
	}
	else if(nMode & UpdateMoveTag){
	}
}

void CMouseTracker::DrawTag(CDC* pDC, CPoint point)
{
	pDC->MoveTo(point.x,point.y);
	pDC->LineTo(point.x-10,point.y-10);
	pDC->LineTo(point.x-50,point.y-10);
	pDC->LineTo(point.x-50,point.y+10);
	pDC->LineTo(point.x-10,point.y+10);
	pDC->LineTo(point.x, point.y);
}

BOOL CMouseTracker::OnSetCursor(CDC *pDC)
{
	if(!pDC)
		return FALSE;
	CPoint point;
	::GetCursorPos(&point);
	m_pWnd->ScreenToClient(& point);
	pDC->DPtoLP(& point);

	int iHandle = HandleTest(point);
	if(iHandle == HandleNothing){ //return FALSE;
		if(m_CreateMode != NoCreate){
			iHandle = m_CreateMode;
		}
		else if(m_Mode == ModeZoomIn)
			iHandle = ModeZoomIn;
		else if(m_Mode == ModeZoomOut)
			iHandle = ModeZoomOut;
		else return FALSE;
	}
	if(iHandle != HandleNothing)
		int i=0;

	return theApp->m_pMainFrame->SetCursor(iHandle);
}

int CMouseTracker::HandleTest(CPoint point)
{
	//if(!m_pSOList->IsEmpty()){
	//	bool bShift = ::GetKeyState(VK_SHIFT) < 0;
	//}
	return HandleNothing;
}

// AdaptWire WILL be VOID!!! after handling points creation
bool CMouseTracker::AdaptWire(CPoint from, CPoint to, AnchorList &addTo)
{
	CPoint lastPoint = to;
	// need to choose 1 of 2 options -> working with better point first (if()...)
	CPoint prevPoint = from;
	CPoint newPnt;
	if(prevPoint.x == lastPoint.x || prevPoint.y == lastPoint.y){ // we have straight line, just have to check if we cross some object or not
		if(prevPoint.x == lastPoint.x){ // vertical line
			int nMaxLength = abs(prevPoint.y - lastPoint.y);
			int nLength = m_pSpaceHash->GetVLine(prevPoint.x, prevPoint.y, lastPoint.y); // pass prevPoint.x as key to the array of registered horizontal CObjects
			if(abs(nLength) >= nMaxLength){// if we can go all the way from->to add this point to anchorlist
				addTo.AddTail(Anchor(CPoint(lastPoint.x, lastPoint.y)));
				return true;// we found straight line with no crossing CObjects
			}
			else{ // we can't go all the way, so try to do all you can
			}
		}
		else{ // horizontal line
			int nMaxLength = abs(prevPoint.x - lastPoint.x);
			int nLength = m_pSpaceHash->GetHLine(prevPoint.y, prevPoint.x, lastPoint.x); // pass prevPoint.y as key to the array of registered vertical CObjects
			if(abs(nLength) >= nMaxLength){ // if we can go all the way from->to add this point to anchorlist
				addTo.AddTail(Anchor(CPoint(lastPoint.x, lastPoint.y)));
				return true; // we found straight line with no crossing CObjects
			}
			else{
			}
		}
	}
	else{
		bool bAdapted = AdaptWireSimple(prevPoint, lastPoint, addTo);
		if(!bAdapted){
			TRACE(_T("pHead not found!Empty priorQueue!!!\n"));
			return false;
		}
		if(m_pPriorQueue->GetSize()){
			CTreeNode *pHead = m_pPriorQueue->GetHead().GetNode();
			TraverseTree(addTo, pHead);
			m_pPriorQueue->RemoveAll();
			return true;
		}
		return false;
		
	}
	return false;
}

bool CMouseTracker::AdaptWireSimple(CPoint from, CPoint to, AnchorList &addTo)
{
	CPoint lastPoint = to;
	CPoint prevPoint = from;
	CSize size = lastPoint - prevPoint;
	CPoint leftPoint, rightPoint;
	CPoint *pAuxPoint = NULL;
	m_pRoot = new CTreeNode(prevPoint, abs(size.cx)+abs(size.cy), NULL);
	m_pPriorQueue = new CPriorQueue<CTreeNode*>();
	m_pPriorQueue->AddFront(m_pRoot,m_pRoot->GetWeight());
	CTreeNode *pTemp = NULL;
	CTreeNode *pAux = NULL;
	int nAuxLength = 0;
	CPoint newPoint;
	bool bFound = false;
	while(m_pPriorQueue->GetSize() && !bFound){
		pTemp = m_pPriorQueue->GetHead().GetNode();
		pAuxPoint = pTemp->GetPoint();
		if(pTemp->GetWeight()){
			m_pPriorQueue->RemoveHead();
			leftPoint.SetPoint(pAuxPoint->x, lastPoint.y);
			rightPoint.SetPoint(lastPoint.x, pAuxPoint->y);
			if((nAuxLength=m_pSpaceHash->GetVLine(leftPoint.x,pAuxPoint->y, leftPoint.y)))
			{
				CPoint pnt(leftPoint.x,pAuxPoint->y+nAuxLength);
				pAux = new CTreeNode(pnt,RecalculateWeight(lastPoint, pnt), pTemp);
				m_pPriorQueue->Add(pAux, pAux->GetWeight());
				pTemp->SetLeft(pAux);
			}
			if((nAuxLength=m_pSpaceHash->GetHLine(rightPoint.y,pAuxPoint->x, rightPoint.x)))
			{
				CPoint pnt(pAuxPoint->x+nAuxLength, rightPoint.y);
				pAux = new CTreeNode(pnt,RecalculateWeight(lastPoint, pnt), pTemp);
				m_pPriorQueue->Add(pAux, pAux->GetWeight());
				pTemp->SetRight(pAux);
			}
		}
		else {
			bFound = true;
		}
	}
	//if(!bFound){
	//	CTreeNode *pMinNode = NULL;
	//	pMinNode = FindMinWeightNode(m_pRoot, m_pRoot);
	//	if(pMinNode != m_pRoot){
	//		TraverseTree(addTo, pMinNode);
	//	}
	//	m_pPriorQueue->RemoveAll();
	//	bFound = true;
	//}
	return bFound;
}

void CMouseTracker::TraverseTree(AnchorList &addTo, CTreeNode *last)
{
	if(last->HasParent()){
		TraverseTree(addTo, last->GetParent());
		pDC->MoveTo(addTo.GetTail().m_PointMain.x, addTo.GetTail().m_PointMain.y);
		addTo.AddTail(Anchor(*last->GetPoint()));
		pDC->LineTo(addTo.GetTail().m_PointMain.x, addTo.GetTail().m_PointMain.y);
		
	}
}

int CMouseTracker::RecalculateWeight(CPoint start, CPoint end)
{
	CSize size = start - end;
	return abs(size.cx) + abs(size.cy);
}

CTreeNode* CMouseTracker::FindMinWeightNode(CTreeNode *pRoot, CTreeNode *pMin)
{
	if(pRoot->HasLeft()){
		pMin = FindMinWeightNode(pRoot->GetLeft(), pMin);
	}
	if(pRoot->HasRight()){
		pMin = FindMinWeightNode(pRoot->GetRight(), pMin);
	}
	if(pMin->GetWeight() > pRoot->GetWeight())
		pMin = pRoot;
	return pMin;
	
}
void CMouseTracker::OnHandScroll(CPoint point)
{
	CSize szScroll = m_PointPrevious - point;
	
	if(szScroll.cx == 10 || szScroll.cx == -10 || szScroll.cy == 10 || szScroll.cy == -10){
		((CINKSView*)m_pView)->OnScrollBy(szScroll);
		TRACE2("ScrollSize: X:%d Y:%d\n", szScroll.cx, szScroll.cy);
	}
}