You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

270 lines
5.4 KiB
C++

#include "stdafx.h"
#include "HandleDrawer.h"
#include "SigmaDoc.h"
#include <atltypes.h>
#include "DrawOperator\CurveEx.h"
#define HANDLE_SIZE 8
#define FOCUS_HANDLE_SIZE 12
static void GetXY(CCurveEx* pValue, int nIndex, dfPoint& point);
static CRect GetHandleRect(long x, long y, bool bFocus);
struct HandlePoint
{
HandlePoint();
int index;
dfPoint ptW; //世界坐标
CPoint ptS; //屏幕坐标
bool bDraw;//未绘制 已经绘制了
};
HandlePoint::HandlePoint()
:index(-1),
bDraw(false)
{
}
HandleDrawer::HandleDrawer(CSigmaDoc * pDoc)
: m_pDoc(pDoc),
m_focusHandle(0)
{
m_colorHandles = RGB(255, 0, 0);
m_headColor = RGB(82, 255, 59);
m_focusHandle = new HandlePoint();
}
HandleDrawer::~HandleDrawer()
{
Release();
delete m_focusHandle;
m_focusHandle = 0;
}
bool HandleDrawer::Init(CCurveEx * pCurve)
{
if (pCurve == NULL)
return false;
Release();
m_focusHandle->index = -1;
dfPoint pt;
HandlePoint * handlePt = 0;
for (int i = 0; i < pCurve->num; i++)
{
//draw handle
GetXY(pCurve, i, pt);
handlePt = new HandlePoint;
handlePt->index = i;
handlePt->ptW = pt;
//TODO:去掉Handle点中的重复点
m_handlePts.push_back(handlePt);
}
return true;
}
void HandleDrawer::ClearAll(CDC * pDC)
{
DrawAllOrEreaseAll(pDC, false);
Release();
if (m_focusHandle->index != -1)
{
DrawOrEreaseOneHandle(pDC, m_focusHandle, false, true); //擦掉focus hanle
}
m_focusHandle->index = -1;
}
void HandleDrawer::DrawAll(CDC * pDC)
{
DrawAllOrEreaseAll(pDC, true);
}
void HandleDrawer::ReDrawAll(CDC * pDC)
{
DrawAllOrEreaseAll(pDC, false);
DrawAllOrEreaseAll(pDC, true);
}
void HandleDrawer::DrawOneHandle(CDC * pDC, int indexOfHandle)
{
if (indexOfHandle < 0 || indexOfHandle >= m_handlePts.size())
{
return;
}
DrawOrEreaseOneHandle(pDC, m_handlePts[indexOfHandle], true, false);
}
void HandleDrawer::DrawFocusHandle(CDC * pDC, int indexOfHandle)
{
if (indexOfHandle < 0 || indexOfHandle >= m_handlePts.size())
{
return;
}
if (m_focusHandle->index == -1) //第一次画 focusHanle
{
*m_focusHandle = *m_handlePts[indexOfHandle];
m_focusHandle->bDraw = false;
DrawOrEreaseOneHandle(pDC, m_focusHandle, true, true);
DrawOrEreaseOneHandle(pDC, m_handlePts[indexOfHandle], false, false); //擦去焦点Handle对应普通Handle
return;
}
if (m_focusHandle->index != indexOfHandle)
{
DrawOrEreaseOneHandle(pDC, m_focusHandle, false, true); //擦掉老的节点
DrawOrEreaseOneHandle(pDC, m_handlePts[indexOfHandle], false, false);
*m_focusHandle = *m_handlePts[indexOfHandle];
m_focusHandle->bDraw = false;
DrawOrEreaseOneHandle(pDC, m_focusHandle, true, true); //画上新的节点
return;
}
//是同一个节点
if (!m_focusHandle->bDraw)
{
DrawOrEreaseOneHandle(pDC, m_focusHandle, true, true);
DrawOrEreaseOneHandle(pDC, m_handlePts[indexOfHandle], false, false);
}
}
//返回擦除节点的索引
int HandleDrawer::EreaseFocusHandle(CDC * pDC)
{
if (pDC == 0)
return -1;
if (m_focusHandle->index == -1)
return -1;
if (m_focusHandle->bDraw)
{
DrawOrEreaseOneHandle(pDC, m_focusHandle, false, true);
}
int index = m_focusHandle->index;
m_focusHandle->index = -1;
m_focusHandle->bDraw = false;
return index;
}
void HandleDrawer::DrawAllOrEreaseAll(CDC * pDC, bool bDrawAll)
{
if (m_handlePts.size() == 0)
return;
size_t count = m_handlePts.size();
HandlePoint * handlePt = 0;
for (size_t i = 0; i < count; i++)
{
handlePt = m_handlePts[i];
if (bDrawAll)
{
if (!handlePt->bDraw)
{
DrawHandle(pDC, handlePt, false);
handlePt->bDraw = true;
}
}
else
{
if (handlePt->bDraw) //已经画上的 Handle 在画一遍就擦掉了
{
DrawHandle(pDC, handlePt, false);
handlePt->bDraw = false;
}
}
} //end for
}
void HandleDrawer::DrawOrEreaseOneHandle(CDC * pDC, HandlePoint * handlePt, bool bDraw, bool bFocus)
{
if (bDraw)
{
if (!handlePt->bDraw)
{
DrawHandle(pDC, handlePt, bFocus);
handlePt->bDraw = true;
}
}
else
{
if (handlePt->bDraw)
{
DrawHandle(pDC, handlePt, bFocus);
handlePt->bDraw = false;
}
}
}
void HandleDrawer::DrawHandle(CDC * pDC, HandlePoint * handlePt, bool bFocus)
{
if (handlePt == 0)
return;
if (handlePt->index == -1)
return;
long ptX = m_pDoc->GetDC().GetSX(handlePt->ptW.x0);
long ptY = m_pDoc->GetDC().GetSY(handlePt->ptW.y0);
CRect rect = GetHandleRect(ptX, ptY, bFocus);
int od = pDC->SetROP2(R2_NOTXORPEN);
CBrush brush, *pOldBrush;
pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
COLORREF color = m_colorHandles;
if (handlePt->index == 0) //使用不同的颜色绘制头节点
color = m_headColor;
CPen penHandles(PS_SOLID, 0, color);
CPen* op = (CPen*)pDC->SelectObject(&penHandles);
pDC->Ellipse(&rect);
pDC->SelectObject(pOldBrush);
pDC->SelectObject(op);
if (od >= 0)
pDC->SetROP2(od);
}
void HandleDrawer::Release()
{
auto ite = m_handlePts.begin();
auto iteEnd = m_handlePts.end();
for (; ite != iteEnd; ite++) {
delete (*ite);
}
m_handlePts.clear();
}
static CRect GetHandleRect(long x, long y, bool bFocus)
{
//m_HandleSize=::GetPreferences().WorkaroundHandle.m_nHandleSize;
int handleSize = HANDLE_SIZE;
if (bFocus)
handleSize = FOCUS_HANDLE_SIZE;
CRect rc; rc.SetRectEmpty();
rc.OffsetRect(x, y);
int d = handleSize / 2;
rc.InflateRect(d, d);
return rc;
}
static void GetXY(CCurveEx* pValue, int nIndex, dfPoint& point)
{
point.x0 = pValue->x[nIndex];
point.y0 = pValue->y[nIndex];
point.z0 = pValue->z[nIndex];
point.l = pValue->l[nIndex];
}