/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2024, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2024 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include "DbMleaderMultiModesGripPE.h" //---------------------------------------------------------------------------------------- #include "DbMLeader.h" #include "DbCommandContext.h" #include "Gs/Gs.h" #include "DbLine.h" //######################################################################################## //############### OdDbMleaderMultiModesGripPE ############## //######################################################################################## ODRX_NO_CONS_DEFINE_MEMBERS(OdGripMLeaderMultiModeAppData, OdRxObject); bool OdDbMLeaderMultiModesGripPE::getGripModes(const OdDbEntity* pEnt, OdDbGripData* pGripData, OdArray& modes, unsigned int& curMode) const { if (!pEnt || !pGripData) return false; OdGripMLeaderMultiModeAppDataPtr appData = static_cast(pGripData->appData()); if (!appData) return false; appData->getGripModes(modes); curMode = appData->mode(); return true; } unsigned int OdDbMLeaderMultiModesGripPE::mode(OdDbEntity*, OdDbGripData* pGripData) const { OdGripMLeaderMultiModeAppDataPtr appData = static_cast(pGripData->appData()); return appData->mode(); } OdDbMultiModesGripPE::GripMode OdDbMLeaderMultiModesGripPE::modeEx(OdDbEntity*, OdDbGripData* pGripData) const { OdGripMLeaderMultiModeAppDataPtr appData = static_cast(pGripData->appData()); return appData->gripMode(); } namespace Trackers { class MLeaderBasicTracker : public OdStaticRxObject { public: MLeaderBasicTracker() = delete; MLeaderBasicTracker(const OdDbMLeaderPtr& org) : m_pMLeader(org->clone()) {} virtual void setValue(const OdGePoint3d& value) = 0; virtual int addDrawables(OdGsView* pView) override { pView->add(m_pMLeader, 0); return 1; } virtual void removeDrawables(OdGsView* pView) override { pView->erase(m_pMLeader); } protected: OdDbMLeaderPtr m_pMLeader; }; class AddLeaderTracker : public MLeaderBasicTracker { public: AddLeaderTracker() = delete; AddLeaderTracker(const OdDbMLeaderPtr& org) : MLeaderBasicTracker(org) { } virtual void setValue(const OdGePoint3d& value) override { if (m_curLeaderIdx != -1) m_pMLeader->removeLeaderLine(m_curLeaderIdx); m_pMLeader->addLeaderLine(value, m_curLeaderIdx); } private: int m_curLeaderIdx = -1; // -1 default value, because all leaders starts at 0 }; class StretchTracker : public MLeaderBasicTracker { public: StretchTracker() = delete; StretchTracker(const OdDbMLeaderPtr& org, OdGePoint3d gripPnt, const OdIntArray& indices) : MLeaderBasicTracker(org), m_pOrg(org), m_gripPnt(gripPnt), m_indices(indices) { } virtual void setValue(const OdGePoint3d& pnt) override { m_pMLeader->copyFrom(m_pOrg); m_pMLeader->moveGripPointsAt(m_indices, pnt - m_gripPnt); } private: const OdDbMLeaderPtr m_pOrg; const OdGePoint3d m_gripPnt; const OdIntArray& m_indices; }; class LeaderStretchTracker : public MLeaderBasicTracker { public: LeaderStretchTracker() = delete; LeaderStretchTracker(const OdDbMLeaderPtr& org, int leaderLineIndex) : MLeaderBasicTracker(org), m_leaderLineIndex(leaderLineIndex) { } virtual void setValue(const OdGePoint3d& value) override { m_pMLeader->setVertex(m_leaderLineIndex, 0,value); } private: const int m_leaderLineIndex; }; class AddVertexTracker : public MLeaderBasicTracker { public: AddVertexTracker() = delete; AddVertexTracker(const OdDbMLeaderPtr& org, int leaderLineIndex) : MLeaderBasicTracker(org), m_leaderLineIndex(leaderLineIndex) { m_pMLeader->addFirstVertex(m_leaderLineIndex, OdGePoint3d::kOrigin); } virtual void setValue(const OdGePoint3d& pnt) override { m_pMLeader->setVertex(m_leaderLineIndex, 0, pnt); } private: const int m_leaderLineIndex; }; class TwoLinesTracker : public OdStaticRxObject { public: TwoLinesTracker() = delete; TwoLinesTracker(OdGePoint3d start, OdGePoint3d end) : m_pLine1(OdDbLine::createObject()), m_pLine2(OdDbLine::createObject()) { m_pLine1->setStartPoint(start); m_pLine1->setEndPoint(start); m_pLine2->setStartPoint(end); m_pLine2->setEndPoint(end); } virtual void setValue(const OdGePoint3d& value) { m_pLine1->setEndPoint(value); m_pLine2->setStartPoint(value); } virtual int addDrawables(OdGsView* pView) { pView->add(m_pLine1, 0); pView->add(m_pLine2, 0); return 1; } virtual void removeDrawables(OdGsView* pView) { pView->erase(m_pLine1); pView->erase(m_pLine2); } private: OdDbLinePtr m_pLine1; OdDbLinePtr m_pLine2; }; } bool OdDbMLeaderMultiModesGripPE::setMode(OdDbEntity* pEnt, OdDbGripData* pGripData, unsigned int newMode) { OdDbMLeaderPtr pMLeader = pEnt; OdDbDatabase* pDb = pMLeader->database(); OdDbCommandContextPtr pCmdCtx = OdDbCommandContext::registredCommandContext(pDb); OdDbUserIO* pIO = pCmdCtx->dbUserIO(); if (!pGripData) return false; OdGripMLeaderMultiModeAppDataPtr appData = static_cast(pGripData->appData()); if (!appData) return false; appData->setMode(newMode); const OdDbMultiModesGripPE::GripMode curMode = appData->gripMode(); pDb->startUndoRecord(); pIO->setLASTPOINT(pGripData->gripPoint()); try { switch (newMode) { case 101: { int nKeyword = 0; bool bKeyword = false; OdIntArray indices; appData->getIndices(indices); try { Trackers::StretchTracker tracker(pMLeader, pGripData->gripPoint(), indices); OdGePoint3d pnt = pIO->getPoint(curMode.CLIPromptString, OdEd::kGptRubberBand, &pGripData->gripPoint(), curMode.CLIKeywordList, &tracker); pMLeader->moveGripPointsAt(indices, pnt - pGripData->gripPoint()); } catch (const OdEdKeyword& kwd) { bKeyword = true; nKeyword = kwd.keywordIndex(); } catch (...) { throw; } if (bKeyword && nKeyword == 0) return false; break; } case 102: { Trackers::AddVertexTracker tracker(pMLeader, appData->m_indices.m_lineIdx); OdGePoint3d pnt = pIO->getPoint(curMode.CLIPromptString, OdEd::kGptRubberBand, &pGripData->gripPoint(), curMode.CLIKeywordList, &tracker); pMLeader->addFirstVertex(appData->m_indices.m_lineIdx, pnt); break; } case 103: { pIO->putString(curMode.CLIPromptString); pMLeader->removeLeaderLine(appData->m_indices.m_lineIdx); break; } case 104: { int nVertices = 0; if (pMLeader->numVertices(appData->m_indices.m_lineIdx, nVertices) != eOk) return false; OdGePoint3dArray pntArr; for (int i = 0; i < nVertices; ++i) { OdGePoint3d ptVertex; pMLeader->getVertex(appData->m_indices.m_lineIdx, i, ptVertex); pntArr.append(ptVertex); } unsigned indexPnt = 0; if (!pntArr.find(pGripData->gripPoint(), indexPnt, 1)) return false; Trackers::TwoLinesTracker tracker(pntArr[indexPnt - 1], pntArr[indexPnt]); OdGePoint3d pnt = pIO->getPoint(curMode.CLIPromptString, OdEd::kGptRubberBand, &pGripData->gripPoint(), curMode.CLIKeywordList, &tracker); pMLeader->addFirstVertex(appData->m_indices.m_lineIdx, OdGePoint3d::kOrigin); unsigned i = 0; for (const auto& p : pntArr) { if (i == indexPnt) pMLeader->setVertex(appData->m_indices.m_lineIdx, i++, pnt); pMLeader->setVertex(appData->m_indices.m_lineIdx, i++, p); } break; } case 105: { pIO->putString(curMode.CLIPromptString); int nVertices = 0; if (pMLeader->numVertices(appData->m_indices.m_lineIdx, nVertices) != eOk) return false; OdGePoint3dArray pntArr; for (int i = 0; i < nVertices; ++i) { OdGePoint3d ptVertex; pMLeader->getVertex(appData->m_indices.m_lineIdx, i, ptVertex); pntArr.append(ptVertex); } pntArr.removeAt(appData->m_indices.m_vertexIdx); pMLeader->removeFirstVertex(appData->m_indices.m_lineIdx); for (unsigned i = 0; i < pntArr.size(); ++i) pMLeader->setVertex(appData->m_indices.m_lineIdx, i, pntArr[i]); break; } case 106: { for (;;) { Trackers::AddLeaderTracker tracker(pMLeader); int index = 0; try { OdGePoint3d pnt = pIO->getPoint(curMode.CLIPromptString, OdEd::kInpThrowEmpty, &pGripData->gripPoint(), curMode.CLIKeywordList, &tracker); pMLeader->addLeaderLine(pnt, index); } catch (const OdEdCancel&) { return true; } } break; } } } catch (const OdEdCancel&) { return false; } return true; } OdDbMultiModesGripPE::GripType OdDbMLeaderMultiModesGripPE::gripType(OdDbEntity*, OdDbGripData* pGripData) const { if (pGripData) { OdGripMLeaderMultiModeAppDataPtr appData = static_cast(pGripData->appData()); if (appData) return appData->gripType(); } return OdDbMultiModesGripPE::kPrimary; } void OdDbMLeaderMultiModesGripPE::reset(OdDbEntity*) { } void OdGripMLeaderMultiModeAppData::getGripModes(OdArray& modes) { for (const auto& mode : m_modes) modes.append(mode.second); } void OdGripMLeaderMultiModeAppData::initGripModes(const MLeaderGripType type) { if (!m_modes.empty() || (type != LEADER && type != VERTEX && type != LANDING)) return; { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 101; mode.DisplayString = "Stretch"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** STRETCH **"; mode.CLIPromptString = "Specify stretch point or [eXit]:"; mode.CLIKeywordList = "eXit"; m_modes[mode.Mode] = mode; } if (type == LEADER) { { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 102; mode.DisplayString = "Add Vertex"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** ADD VERTEX **"; mode.CLIPromptString = "Specify new vertex point:"; m_modes[mode.Mode] = mode; } { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 103; mode.DisplayString = "Remove Leader"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** REMOVE LEADER **"; mode.CLIPromptString = "Pick to remove leader:"; m_modes[mode.Mode] = mode; } } else if (type == VERTEX) { { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 104; mode.DisplayString = "Add Vertex"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** ADD VERTEX **"; mode.CLIPromptString = "Specify new vertex point:"; m_modes[mode.Mode] = mode; } { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 105; mode.DisplayString = "Remove Vertex"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** REMOVE VERTEX **"; mode.CLIPromptString = "Pick to remove vertex:"; m_modes[mode.Mode] = mode; } } else if (type == LANDING) { OdDbMultiModesGripPE::GripMode mode; mode.Mode = 106; mode.DisplayString = "Add Leader"; mode.ActionType = OdDbMultiModesGripPE::GripActionType::kImmediate; mode.CLIDisplayString = "** ADD LEADER **"; mode.CLIPromptString = "Specify leader arrowhead location:"; m_modes[mode.Mode] = mode; } } bool OdGripMLeaderMultiModeAppData::getIndices(OdIntArray& indices) const { indices.append(m_indices.m_gripIdx); return true; }