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.
kev/Drawer/Module/GeoSigmaDraw/CurveEditorBase.cpp

617 lines
15 KiB
C++

1 month ago
#include "StdAfx.h"
#include "ActionBackupItem.h"
#include "ActionCurveEdit.h"
#include "ActionCurveEditAddPoint.h"
#include "ActionCurveEditDeletePoint.h"
#include "ActionModifiedItem.h"
#include "DrawOperator/TypeDefine.h"
#include "HandleDrawer.h"
#include "SigmaDoc.h"
#include "SigmaView.h"
#include "CurveEditorBase.h"
namespace NItem {
CurveEditorBase::CurveEditorBase(CSigmaDoc *pDoc)
: CItemCurve(pDoc), m_bLButtonDownWhenMouseMove(false),
m_nHandleDrawMode(TRACKER_CIRCLE),
m_handleDrawer(std::make_unique<HandleDrawer>(pDoc)), m_nModeX(-1),
m_nModeY(-1) {}
CurveEditorBase::~CurveEditorBase(void) {}
void CurveEditorBase::OnDraw(CXyDC *pDC) {
POSITION pos = GetPos();
if (pos == 0)
return;
// ?????????????????
CCurveEx *pCurve = (CCurveEx *)GetDoc()->GetDraw()->GetAtValue(GetPos());
}
void CurveEditorBase::DrawAssistant(CDC *pDC, int mouseX, int mouseY) {
CCurveEx *pCurve = GetControlCurve();
if (pCurve == nullptr)
return;
m_handleDrawer->Init(pCurve);
m_handleDrawer->DrawAll(pDC);
}
void CurveEditorBase::OnLButtonDown(CDC *pDC, UINT nFlags, CPoint point,
int vk) {
SetScreenDC(pDC);
// ??<3F><>????????<3F><>????????????????
if (this->GetHandleIndex() < 0) {
if (!IsCanAddHandle(point))
return;
}
// ?????<3F><>???????<3F><>?
if (NewPointList.GetCount() > 0)
NewPointList.RemoveAll();
// ????????<3F><>???????????????????
m_nLButtonDownPoint = point;
c_down = GetDC()->GetReal(point);
c_last = c_down;
// ????????????????
this->OnDrawDragPreview();
}
int CurveEditorBase::OnMouseMove(CDC *dc, UINT nFlags, CPoint point) {
SetScreenDC(dc);
POSITION pos = GetPos();
if (pos == 0)
return 1;
CXyDC *pDC = GetDC();
if (IsDragging(nFlags)) // ??????????
{
HandleMouseDrag(pDC, point);
} else {
HandleMouseHover(dc, point);
}
m_handleDrawer->DrawFocusHandle(dc, GetHandleIndex());
return 1;
}
void CurveEditorBase::OnLButtonUp(CDC *pDC, UINT nFlags, CPoint point, int vk) {
SetScreenDC(pDC);
if (m_bLButtonDownWhenMouseMove == false)
return;
m_bLButtonDownWhenMouseMove = false;
if (this->GetHandleIndex() < 0) {
CPoint2D pt = GetDC()->GetReal(point);
POSITION pos = GetDoc()->GetSelectedItem(pt);
if (pos == GetPos())
return;
EndEdit();
return;
}
c_last = GetDC()->GetReal(point);
// ?????????
OnDrawDragPreview();
if (c_last == c_down)
return;
// ??????
OnCalculateDragEffect(nullptr);
SetModifiedFlag(TRUE);
GetDoc()->Modified();
SetHandleIndex(-1);
ReleaseCapture();
}
void CurveEditorBase::OnLButtonDblClk(UINT nFlags, CPoint point) {
POSITION pos = GetPos();
if (pos == nullptr)
return;
COne *pOne = GetDoc()->GetDraw()->GetAt(pos);
if (pOne == nullptr)
return;
std::unique_ptr<CActionModifiedItem> pAction =
std::make_unique<CActionModifiedItem>(GetDoc(), 0);
pAction->BackupOldItem(pos, pOne);
if (GetHandleIndex() >= 0) {
if (IsCaptureState())
ReleaseCapture();
int index = GetHandleIndex();
CCurveEx *pcurve = GetControlCurve();
CRect8 range(1e300, -1e300, -1e300, 1e300);
for (int i = index - 1; i <= index + 1; i++) {
if (i < 0 || i > pcurve->num - 1)
continue;
range.CombinRect(pcurve->x[i], pcurve->y[i], pcurve->x[i], pcurve->y[i]);
}
DeleteHandle(GetHandleIndex());
SetHandleIndex(-1);
CRect rt = GetDC()->GetScreen(range);
CSize8 sz = GetDoc()->GetSelectSize();
CSize size((int)sz.cx + 1, (int)sz.cy + 1);
rt.InflateRect(size);
} else if (IsCanAddHandle(point)) {
int ret = AddHandle(point);
if (ret < 0)
return;
}
pAction->BackupNewItem();
GetDoc()->SetActionItem(pAction.release());
GetDoc()->Modified();
if (GetDoc()->GetItem()->GetType() == ITEM_CURVE_EDIT) {
EndEdit();
}
}
BOOL CurveEditorBase::OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message) {
return TRUE;
}
BOOL CurveEditorBase::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
switch (nChar) {
case VK_ESCAPE:
if (!IsCaptureState())
break;
OnDrawDragPreview();
DrawSelectHandle(GetHandleIndex());
SetHandleIndex(-1);
ReleaseCapture();
return TRUE;
}
return FALSE;
}
BOOL CurveEditorBase::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) {
switch (nChar) {
case VK_ESCAPE:
EndEdit();
return TRUE;
}
return FALSE;
}
int CurveEditorBase::GetSubMenu() { return 6; }
void CurveEditorBase::SetPos(POSITION pos) {
CItem::SetPos(pos);
m_pBakOne.reset(); // ????????
if (pos) {
COne *pOne = GetDoc()->GetDraw()->GetAt(GetPos());
m_pBakOne = std::make_unique<COne>();
*m_pBakOne = *pOne;
// ???<3F><>????????????????????????????m_pMarkCurve??
OnModeInitialize();
}
}
void CurveEditorBase::Clear(void) {
m_pBakOne.reset(); // ???????
if (GetPos() != nullptr) {
COne *pOne = GetDoc()->GetDraw()->GetAt(GetPos());
CRect8 range(1e100, -1e100, -1e100, 1e100);
pOne->GetRange(range);
CRect rt = GetDC()->GetScreen(range);
rt.NormalizeRect();
rt.InflateRect(GetDoc()->GetHandleSize());
rt.InflateRect(1, 1);
}
}
void CurveEditorBase::Draw(CDC *pDC) {
POSITION pos = GetPos();
if (pos == 0)
return;
CCurveEx *pValue = GetControlCurve();
DrawHandlesByCDC(pDC, pValue);
}
int CurveEditorBase::GetNumberOfNode() {
CCurveEx *pc = GetControlCurve();
if (pc == 0)
return -1;
return pc->num;
}
void CurveEditorBase::EreaseHandles(CDC *pDC) { m_handleDrawer->ClearAll(pDC); }
// ========== ????????????????==========
void CurveEditorBase::EndEdit(void) {
if (GetPos() == nullptr)
return;
COne *pOne = GetDoc()->GetDraw()->GetAt(GetPos());
CRect8 range(1e100, -1e100, -1e100, 1e100);
pOne->GetRange(range);
CRect rt = GetDC()->GetScreen(range);
rt.NormalizeRect();
rt.InflateRect(GetDoc()->GetHandleSize());
rt.InflateRect(1, 1);
if (((CCurveEx *)pOne->GetValue())->num < 2) {
if (::AfxMessageBox(IDS_STRING_CURVE_ONLY_ONE_POINT,
MB_YESNO | MB_ICONQUESTION) == IDYES) {
*pOne = *m_pBakOne;
CPositionList list;
list.AddTail(GetPos());
CItem::SetPos(nullptr);
GetDoc()->InvalidateDelete(list);
return;
}
}
if (IsModified()) {
CActionItem *pAction =
new CActionModifiedItem(GetDoc(), IDS_STRING_TOOLBAR_EDIT);
((CActionModifiedItem *)pAction)->BackupOldItem(GetPos(), m_pBakOne.get());
GetDoc()->SetActionItem(pAction);
}
}
void CurveEditorBase::CancelAll(void) {
if (m_pBakOne) {
COne *pOne = GetDoc()->GetDraw()->GetAt(GetPos());
*pOne = *m_pBakOne;
GetMarkCurve();
}
}
BOOL CurveEditorBase::IsCanCancelAll(void) {
return m_pBakOne != nullptr ? TRUE : FALSE;
}
void CurveEditorBase::GetXY(CCurveEx *pValue, int nIndex, dfPoint &point) {
pValue->GetPoint(nIndex, point);
}
CCurveEx *CurveEditorBase::GetControlCurve(void) {
POSITION pos = GetPos();
if (pos == nullptr)
return nullptr;
return (CCurveEx *)GetDoc()->GetDraw()->GetAtValue(pos);
}
int CurveEditorBase::HitTestHandle(CPoint point) {
return HitTestHandle(GetControlCurve(), point);
}
int CurveEditorBase::HitTestHandle(CCurveEx *pValue, CPoint point) {
if (pValue == nullptr)
return -1;
CRect rt;
for (int i = 0; i < pValue->num; i++) {
rt = GetDoc()->m_itemTracker.GetHandleRect(GetDC()->GetSX(pValue->x[i]),
GetDC()->GetSY(pValue->y[i]));
if (rt.PtInRect(point))
return i;
}
return -1;
}
bool CurveEditorBase::IsDragging(int nFlags) const { return nFlags & 1; }
int CurveEditorBase::HandleMouseDrag(CXyDC *pDC, CPoint point) {
m_bLButtonDownWhenMouseMove = true;
// ?????????????????????????????????????????????????
int i = GetHandleIndex();
if (i < 0) {
CSize8 sz = GetDoc()->GetSelectSize();
if (AfxGetPublicFunction()->Distance(m_nLButtonDownPoint.x,
m_nLButtonDownPoint.y, point.x,
point.y) > sz.cx) {
i = AddHandle(m_nLButtonDownPoint);
if (i < 0)
return 1;
SetHandleIndex(i);
c_down = GetDC()->GetReal(m_nLButtonDownPoint);
c_last = c_down;
// ????<3F><>????????
OnDrawDragPreview();
} else
return 1;
}
// ????????<3F><>????
OnDrawDragPreview();
// ????<3F><>??
c_last = pDC->GetReal(point);
CPointList list;
OnCalculateDragEffect(&list);
// ?????<3F><>???????????o?? NewPointList??
OnDrawDragPreview();
CString str, string;
auto curve = std::make_unique<CCurveEx>();
curve->SetPoints(list, 2);
COne *pOne = GetDoc()->GetDraw()->GetAt(GetPos());
CCurveEx *pValue = (CCurveEx *)pOne->GetValue();
OnDragMove(GetHandleIndex(), c_last);
return 1;
}
int CurveEditorBase::HandleMouseHover(CDC *dc, CPoint point) {
// ???????????????????
CCurveEx *pValue = GetControlCurve();
if (pValue == 0) {
SetHandleIndex(-1);
int handleIndex = m_handleDrawer->EreaseFocusHandle(dc);
m_handleDrawer->DrawOneHandle(dc, handleIndex);
} else {
int i = HitTestHandle(pValue, point);
if (i >= 0) {
SetHandleIndex(i);
} else {
SetHandleIndex(-1);
int handleIndex = m_handleDrawer->EreaseFocusHandle(dc);
m_handleDrawer->DrawOneHandle(dc, handleIndex);
}
}
return 1;
}
void CurveEditorBase::DeleteHandle(int nIndex) {
CCurveEx *pValue = GetControlCurve();
BOOL bAttachProcess = TRUE;
CPointList oldPoints;
CPointList newPoints;
if (bAttachProcess) {
dfPoint pt;
if (nIndex != 0) {
pValue->GetPoint(nIndex - 1, pt);
oldPoints.AddTail(pt);
newPoints.AddTail(pt);
}
pValue->GetPoint(nIndex, pt);
oldPoints.AddTail(pt);
if (nIndex < pValue->num - 1) {
pValue->GetPoint(nIndex + 1, pt);
oldPoints.AddTail(pt);
newPoints.AddTail(pt);
}
}
PointList.RemoveAll();
dfPoint dd;
for (int i = 0; i < pValue->num; i++) {
dd.x0 = pValue->x[i];
dd.y0 = pValue->y[i];
dd.z0 = pValue->z[i];
dd.l = pValue->l[i];
if (i == nIndex)
continue;
PointList.AddTail(dd);
}
pValue->SetPoints(PointList, pValue->nPoint, pValue->bAutoLocation);
PointList.RemoveAll();
SetModifiedFlag(TRUE);
this->SetHandleIndex(-1);
if (bAttachProcess) {
if (oldPoints.GetCount() > 0)
AttachProcess(oldPoints, newPoints);
}
}
int CurveEditorBase::AddHandle(double l0) {
CCurveEx *pValue = (CCurveEx *)GetDoc()->GetDraw()->GetAtValue(GetPos());
dfPoint add;
add.l = l0;
pValue->GetCoordinate(add.l, add.x0, add.y0, add.z0);
return AddHandle(pValue, add);
}
int CurveEditorBase::AddHandle(CCurveEx *pValue, dfPoint add) {
if (pValue == nullptr)
return -1;
int nIndex = -1;
PointList.RemoveAll();
if (add.l < pValue->l[0]) {
pValue->GetPoint(PointList);
PointList.AddHead(add);
nIndex = 0;
} else if (add.l > pValue->l[pValue->num - 1]) {
pValue->GetPoint(PointList);
PointList.AddTail(add);
nIndex = (int)PointList.GetCount() - 1;
} else {
dfPoint dd;
for (int i = 0; i < pValue->num; i++) {
dd.x0 = pValue->x[i];
dd.y0 = pValue->y[i];
dd.z0 = pValue->z[i];
dd.l = pValue->l[i];
PointList.AddTail(dd);
if (i == pValue->num - 1)
break;
if (add.l > pValue->l[i] && add.l < pValue->l[i + 1]) {
PointList.AddTail(add);
nIndex = i + 1;
}
}
}
pValue->SetPoints(PointList, pValue->nPoint, pValue->bAutoLocation);
PointList.RemoveAll();
GetDoc()->Modified();
SetModifiedFlag(TRUE);
return nIndex;
}
int CurveEditorBase::AddHandle(CPoint point) {
double l0;
if (!IsCanAddHandle(point, &l0))
return -1;
return AddHandle(l0);
}
BOOL CurveEditorBase::IsCanAddHandle(CPoint point, double *pl0) {
POSITION pos = GetPos();
if (pos == nullptr)
return FALSE;
CCurveEx *pValue = (CCurveEx *)GetDoc()->GetDraw()->GetAtValue(pos);
if (pValue == nullptr)
return FALSE;
CPoint2D pt = GetDC()->GetReal(point);
double l0;
double dis = pValue->PointDistance(pt.x0, pt.y0, l0);
CSize8 sz = GetDoc()->GetSelectSize();
int dx = GetDC()->GetScreenWidth(dis);
int dy = GetDC()->GetScreenHeight(dis);
if (pl0)
*pl0 = l0;
if (dx > sz.cx || dy > sz.cy)
return FALSE;
return TRUE;
}
void CurveEditorBase::AttachProcess(CPointList &oldPoints,
CPointList &newPoints) {}
void CurveEditorBase::DrawMoveLine(void) { OnDrawDragPreview(); }
void CurveEditorBase::GetMarkCurve(void) {}
CPoint2D CurveEditorBase::GetCDown() const { return c_down; }
CPoint2D CurveEditorBase::GetCLast() const { return c_last; }
void CurveEditorBase::DrawHandle(CXyDC *pDC, CCurveEx *pCurve) {
if (pCurve == nullptr)
return;
CPoint ptPrev;
CRect rt;
dfPoint pt;
CPoint point;
for (int i = 0; i < pCurve->num; i++) {
GetXY(pCurve, i, pt);
point.x = pDC->GetSX(pt.x0);
point.y = pDC->GetSY(pt.y0);
if (i > 0) {
if (point.x == ptPrev.x && point.y == ptPrev.y && i != GetHandleIndex())
continue;
}
if (i == GetHandleIndex()) {
if (i == 0)
rt = GetFirstNodeHandleRectFocus(point);
else
rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point);
} else {
if (i == 0)
rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point);
else
rt = GetDoc()->m_itemTracker.GetHandleRect(point);
}
GetDoc()->m_itemTracker.DrawHandle(m_pScreenDC, rt, TRACKER_CIRCLE);
ptPrev = point;
}
}
void CurveEditorBase::DrawHandlesByCDC(CDC *pDC, CCurveEx *pCurve) {
if (pCurve == nullptr)
return;
m_handleDrawer->ClearAll(pDC);
m_handleDrawer->Init(pCurve);
m_handleDrawer->DrawAll(pDC);
}
void CurveEditorBase::DrawSelectHandle(int nHandle) {
CCurveEx *pValue = GetControlCurve();
if (pValue == nullptr)
return;
if (nHandle < 0 || nHandle >= pValue->num)
return;
CPoint point;
point.x = GetDC()->GetSX(pValue->x[nHandle]);
point.y = GetDC()->GetSY(pValue->y[nHandle]);
CRect rt;
if (nHandle == 0)
rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point);
else
rt = GetDoc()->m_itemTracker.GetHandleRect(point);
GetDoc()->m_itemTracker.DrawHandle(m_pScreenDC, rt, m_nHandleDrawMode);
if (nHandle == 0)
rt = GetFirstNodeHandleRectFocus(point);
else
rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point);
GetDoc()->m_itemTracker.DrawHandle(m_pScreenDC, rt, m_nHandleDrawMode);
}
CRect CurveEditorBase::GetRangeWidthIndex(int nIndex) {
CCurveEx *pValue = GetControlCurve();
if (pValue == nullptr || nIndex < 0 || nIndex >= pValue->num) {
return CRect(0, 0, 0, 0);
}
CRect8 rt(pValue->x[nIndex], pValue->y[nIndex], pValue->x[nIndex],
pValue->y[nIndex]);
if (nIndex > 0)
rt.CombinRect(pValue->x[nIndex - 1], pValue->y[nIndex - 1],
pValue->x[nIndex - 1], pValue->y[nIndex - 1]);
if (nIndex < pValue->num - 1)
rt.CombinRect(pValue->x[nIndex + 1], pValue->y[nIndex + 1],
pValue->x[nIndex + 1], pValue->y[nIndex + 1]);
CRect rect = GetDC()->GetScreen(rt);
rect.InflateRect(GetDoc()->GetHandleSize());
return rect;
}
CRect CurveEditorBase::GetFirstNodeHandleRectFocus(CPoint point) {
CRect rt = GetDoc()->m_itemTracker.GetHandleRectFocus(point);
rt.InflateRect(1, 1);
return rt;
}
void CurveEditorBase::SetDrawMode(int nModeX, int nModeY) {
m_nModeX = nModeX;
m_nModeY = nModeY;
}
int CurveEditorBase::GetOffsetMode(void) {
return GetDoc()->GetEditLineStatus() % 4;
}
}; // namespace NItem