#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(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); // ??ï“????????§ß???????????????? if (this->GetHandleIndex() < 0) { if (!IsCanAddHandle(point)) return; } // ?????¦Å???????§Ò? if (NewPointList.GetCount() > 0) NewPointList.RemoveAll(); // ????????¦Ë??????????????????? 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 pAction = std::make_unique(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(); *m_pBakOne = *pOne; // ???¨´????????????????????????????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; // ????¦Ë???????? OnDrawDragPreview(); } else return 1; } // ????????¦Å???? OnDrawDragPreview(); // ????¦Ë?? c_last = pDC->GetReal(point); CPointList list; OnCalculateDragEffect(&list); // ?????¦Ì???????????o?? NewPointList?? OnDrawDragPreview(); CString str, string; auto curve = std::make_unique(); 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