Click here to Skip to main content
15,881,248 members
Articles / Desktop Programming / WTL

XONOR pointers: eXclusive Ownership & Non Owning Reference pointers

Rate me:
Please Sign up or sign in to vote.
4.96/5 (46 votes)
14 Apr 2014CPOL41 min read 125.9K   691   88  
A smart pointer system for safe application development in C++.
#pragma once

namespace mouse_modes {

using namespace visual_objects;

enum MOUSE_MODE {Mode_Move, Mode_Line, Mode_Square, Mode_Ellipse};

class CMouseMode
{
protected:	

	ref<CWindowImplBase> m_rWindow;
	ref<CDocument> m_rDocument;

	ref<CVisualObject> m_rVisualObject;
public:
	
	MOUSE_MODE m_MouseModeCode;
	CPoint m_LastMousePoint;

	CMouseMode(ref<CWindowImplBase> rWindow, ref<CDocument> rDocument, MOUSE_MODE MouseModeCode)
	{
		m_rWindow=rWindow;
		m_rDocument=rDocument;
		int i=0;
		m_MouseModeCode=MouseModeCode;
	}
 
	xvirtual ~CMouseMode()
	{
	}
	virtual void OnLButtonDblClk(UINT nFlags, CPoint point)
	{
		m_rVisualObject=m_rDocument->HitTest(point);
		if(m_rVisualObject && m_rDocument)
		{
			m_rDocument->ShowObjectProperties(m_rVisualObject);
		}
		else if(m_rDocument)
			m_rDocument->ShowObjectProperties(NULL);
	}

	virtual void OnLButtonDown(UINT nFlags, CPoint point)=0;
	virtual void OnLButtonUp(UINT nFlags, CPoint point)
	{
		if(m_rDocument && m_rDocument->m_oObjectDlg)
		{
			m_rVisualObject=m_rDocument->HitTest(point);
			if(m_rVisualObject && m_rDocument)
			{
				m_rDocument->ShowObjectProperties(m_rVisualObject);
			}
			else if(m_rDocument)
				m_rDocument->ShowObjectProperties(NULL);
		}
		
	}
	virtual void OnMouseMove(UINT nFlags, CPoint point)=0;
	virtual void SetModeCursor()=0;
};

class CMouseModeMove : public CMouseMode
{

public:
	CMouseModeMove(ref<CWindowImplBase> rWindow, ref<CDocument> rDocument)
		:CMouseMode(rWindow, rDocument, Mode_Move)
	{
		
	}
	~CMouseModeMove()
	{

	}
	virtual void OnLButtonDown(UINT nFlags, CPoint point)
	{
		m_LastMousePoint=point;
		m_rVisualObject=m_rDocument->HitTest(point);
		m_rDocument->SetSelectedVisualObject(m_rVisualObject);
		SetModeCursor();
	}
	virtual void OnLButtonUp(UINT nFlags, CPoint point)
	{
		m_rVisualObject=NULL;
		CMouseMode::OnLButtonUp(nFlags, point);
	}
	virtual void OnMouseMove(UINT nFlags, CPoint point)
	{
		if(nFlags & MK_LBUTTON)
		{
			if(m_rVisualObject)
			{
				m_rVisualObject->MoveBy(point-m_LastMousePoint);
			}
		}
		else
		{
			ref<CVisualObject> rVisualObject=m_rDocument->HitTest(point);
			if(rVisualObject)
			{
				if(rVisualObject->IsSizing())
					SetCursor(AtlLoadCursor(IDC_SIZING));
				else
					SetCursor(AtlLoadCursor(IDC_MOVE));
			}
		}
		m_LastMousePoint=point;
		
	}
	virtual void SetModeCursor()
	{
		if(m_rVisualObject)
		{
			if(m_rVisualObject->IsSizing())
				SetCursor(AtlLoadCursor(IDC_SIZING));
			else
				SetCursor(AtlLoadCursor(IDC_MOVE));
		}
		else
			SetCursor(AtlLoadCursor(IDC_MYARROW));
		
	}
};

class CMouseModeBox;

class CMouseModeBoxMove : public CMouseModeMove
{
	ref<CMouseModeBox> m_rMouseModeBox;
public:
	CMouseModeBoxMove(ref<CWindowImplBase> rWindow, ref<CDocument> rDocument, ref<CMouseModeBox> rMouseModeBox)
		: CMouseModeMove(rWindow, rDocument)
	{
		m_rMouseModeBox=rMouseModeBox;
	}
	~CMouseModeBoxMove()
	{

	}
	virtual void OnMouseMove(UINT nFlags, CPoint point);
	
};
class CMouseModeBox : public CMouseMode, public enable_ref_ptr_to_this<CMouseModeBox>
{
	CPoint m_DownPoint;
	ref<CBox> m_rNewBox;
	
public:
	owner_ptr<CMouseModeBoxMove> m_oMouseModeBoxMove;

	CMouseModeBox(ref<CWindowImplBase> rWindow, ref<CDocument> rDocument, MOUSE_MODE MouseModeCode)
		:CMouseMode(rWindow, rDocument, MouseModeCode)
	{
		
	}
	~CMouseModeBox()
	{

	}
	virtual void OnLButtonDown(UINT nFlags, CPoint point)
	{
		if(m_oMouseModeBoxMove)
			m_oMouseModeBoxMove->OnLButtonDown(nFlags, point);
		else
			m_DownPoint=point;
		
	}
	virtual void OnLButtonUp(UINT nFlags, CPoint point)
	{
		if(m_oMouseModeBoxMove)
			m_oMouseModeBoxMove->OnLButtonUp(nFlags, point);
		else
			m_rNewBox=NULL;
		CMouseMode::OnLButtonUp(nFlags, point);
	}
	virtual void OnMouseMove(UINT nFlags, CPoint point)
	{
		
		if(m_oMouseModeBoxMove)
		{
			m_oMouseModeBoxMove->OnMouseMove(nFlags,point);
			return;
		}

		if(NULL==m_rDocument)
			return;
		
		ref<CVisualObject> rVisualObject=m_rDocument->HitTest(point);
		if(rVisualObject)
		{
			if(NULL==m_oMouseModeBoxMove)
			{
				int i=0;
				m_oMouseModeBoxMove=new CMouseModeBoxMove(m_rWindow, m_rDocument, ref_ptr_to_this());
			}
			m_oMouseModeBoxMove->OnMouseMove(nFlags, point);
			return;
		}
		else
			m_oMouseModeBoxMove=NULL;
		if(nFlags & MK_LBUTTON && point.x-m_DownPoint.x>15 && point.y-m_DownPoint.y>15)
		{
			if(NULL==m_rNewBox)
			{
				switch(m_MouseModeCode)
				{
				case Mode_Square:
					/*{
					new_ptr<CRectangleBox> newRectangleBox=m_rDocument->NewRectangleBox(m_DownPoint, CSize(point.x-m_DownPoint.x, point.y-m_DownPoint.y));
					m_rDocument->m_VisualObjects.Add(newRectangleBox);
					m_rNewBox=newRectangleBox;
					}*/
					m_rNewBox=m_rDocument->AddRectangleBox(m_DownPoint, CSize(point.x-m_DownPoint.x, point.y-m_DownPoint.y));
					
					
					break;
				case Mode_Ellipse:
					m_rNewBox=m_rDocument->AddEllipseBox(m_DownPoint, CSize(point.x-m_DownPoint.x, point.y-m_DownPoint.y));
				
					break;

				}
				m_rDocument->SetSelectedVisualObject(m_rNewBox);
			}
			else
			{
				m_rNewBox->m_Size=CSize(point.x-m_DownPoint.x, point.y-m_DownPoint.y);
			}
		}
	}
	virtual void SetModeCursor()
	{
		if(m_oMouseModeBoxMove)
		{
			m_oMouseModeBoxMove->SetModeCursor();
			return;
		}
		switch(m_MouseModeCode)
		{
		case Mode_Square:
			SetCursor(AtlLoadCursor(IDC_SQUARE));
			break;
		case Mode_Ellipse:
			SetCursor(AtlLoadCursor(IDC_ELLIPSE));
			break;
		}
	}
};

void CMouseModeBoxMove::OnMouseMove(UINT nFlags, CPoint point)
{
	if(nFlags & MK_LBUTTON)
	{
		if(m_rVisualObject)
		{
			m_rVisualObject->MoveBy(point-m_LastMousePoint);
		}
	}
	else
	{
		ref<CVisualObject> rVisualObject=m_rDocument->HitTest(point);
		if(rVisualObject)
		{
			if(rVisualObject->IsSizing())
				SetCursor(AtlLoadCursor(IDC_SIZING));
			else
				SetCursor(AtlLoadCursor(IDC_MOVE));
		}
		else
		{
			m_rMouseModeBox->m_oMouseModeBoxMove=NULL;
			return;
		}
	}
	m_LastMousePoint=point;
}

class CMouseModeLine : public CMouseMode
{
	ref<CBox> m_rFirstBox;
public:
	CMouseModeLine(ref<CWindowImplBase> rWindow, ref<CDocument> rDocument)
		:CMouseMode(rWindow, rDocument, Mode_Line)
	{
		
	}
	~CMouseModeLine()
	{

	}
	virtual void OnLButtonDown(UINT nFlags, CPoint point)
	{
		CMouseMode::OnLButtonUp(nFlags, point);
	}
	virtual void OnLButtonUp(UINT nFlags, CPoint point)
	{
		m_rVisualObject=m_rDocument->HitTest(point);
		ref<CVisualObject> rVO=m_rVisualObject;
		if(m_rVisualObject && m_rVisualObject->GetType().Find(_T("Box"))>-1)
		{
			if(NULL==m_rFirstBox)
				m_rFirstBox=up_cast<CBox, CVisualObject>(m_rVisualObject);
			else if(m_rVisualObject!=m_rFirstBox && false==m_rFirstBox->HasLineTo(up_cast<CBox, CVisualObject>(m_rVisualObject)))
			{
				m_rDocument->AddLine(m_rFirstBox, up_cast<CBox, CVisualObject>(m_rVisualObject));
				m_rFirstBox=NULL;
			}
			else
				m_rFirstBox=NULL;
			m_rDocument->SetSelectedVisualObject(m_rVisualObject);
		}
		else
			m_rFirstBox=NULL;
		m_rWindow->Invalidate();
		m_rWindow->UpdateWindow();
		SetModeCursor();
	}
	virtual void OnMouseMove(UINT nFlags, CPoint point)
	{
		if(NULL==m_rDocument)
			return;;
		m_rVisualObject=m_rDocument->HitTest(point);
		if(m_rFirstBox)
		{
			CClientDC dc(m_rWindow->m_hWnd);
			
			ref<CVisualObject> rVisualObject=m_rDocument->m_rSelectedVisualObject;
			m_rDocument->m_rSelectedVisualObject=NULL;
			m_rWindow->Invalidate();
			m_rWindow->UpdateWindow();
			m_rDocument->m_rSelectedVisualObject=rVisualObject;

			dc.MoveTo(m_rFirstBox->GetCentrePoint());
			dc.LineTo(point);
		
		}
	}
	virtual void SetModeCursor()
	{
		if(m_rFirstBox)
		{
			if(m_rVisualObject && m_rVisualObject!=m_rFirstBox && false==m_rFirstBox->HasLineTo(up_cast<CBox, CVisualObject>(m_rVisualObject)))
				SetCursor(AtlLoadCursor(IDC_SECOND_POINT));
			else
				SetCursor(AtlLoadCursor(IDC_HALFLINE));
		}
		else
		{
			if(m_rVisualObject)
				SetCursor(AtlLoadCursor(IDC_FIRST_POINT));
			else
				SetCursor(AtlLoadCursor(IDC_LINE));
		}
	}
};

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired
Spain Spain
Software Author with engineering, science and mathematical background.

Many years using C++ to develop responsive visualisations of fine grained dynamic information largely in the fields of public transport and supply logistics. Currently interested in what can be done to make the use of C++ cleaner, safer, and more comfortable.

Comments and Discussions