/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2019, 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-2019 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// // // DgSysVarPEImpl.cpp // #include "OdaCommon.h" #include "DgSysVarPEImpl.h" #include "ExAppServices.h" #include "PropServices.h" #include "StaticRxObject.h" #include "RxDictionary.h" #include "DgDatabase.h" #include "DgHostAppServices.h" #define STL_USING_MAP #include "OdaSTL.h" #include "Ed/EdCommandContext.h" #include "Ed/EdUserIO.h" /////////////////////////////////////////////////////////////////////////////// // it's here to prevent inconvenient linking with OdaQtConsole #if defined(ODA_SYS_VAR_PE_UNLINKED_RXINIT) && defined(_TOOLKIT_IN_DLL_) ODRX_NO_CONS_DEFINE_MEMBERS(OdSysVarPE, OdRxObject); #endif //OdRxClass* OdSysVarPE::g_pDesc = NULL; //OdRxClass* OdSysVarPE::desc() //{ // return g_pDesc; //} //OdRxClass* OdSysVarPE::isA() const //{ // return g_pDesc; //} // //OdRxObject* OdSysVarPE::queryX(const OdRxClass* pClass) const //{ // return ::odQueryXImpl(this, pClass); //} // it's here to prevent impossible linking with OdaQtApp : #if defined(ODA_PROP_SERVICES_UNLINKED_RXINIT) && defined(_TOOLKIT_IN_DLL_) ODRX_NO_CONS_DEFINE_MEMBERS(OdPropServices, OdRxObject); #endif // it's here to prevent impossible linking with OdaQtApp : #if defined(ODA_EX_APP_SERVICES_UNLINKED_RXINIT) && defined(_TOOLKIT_IN_DLL_) ODRX_NO_CONS_DEFINE_MEMBERS(ExAppServices, OdRxObject); #endif /////////////////////////////////////////////////////////////////////////////// class OdDgSysVarPEImpl : public OdSysVarPE { public: ODRX_DECLARE_MEMBERS(OdDgSysVarPEImpl); // pRxObject - is OdDbBaseDatabase virtual bool getNames(OdRxObject* pRxObject, OdStringArray& names, bool bSkipHidden = true); virtual OdString valueToString(OdRxObject* pRxObject, const OdString& sName, OdSysVarType* pRbType = NULL, bool* pbExist = NULL); virtual bool isEditable(OdRxObject* pRxObject, const OdString& sName, bool* pbExist = NULL); virtual bool editValue(OdEdCommandContext* pCmdCtx, const OdString& sName, bool* pbExist = NULL); }; //typedef OdSmartPtr OdDgSysVarPEImplPtr; ODRX_NO_CONS_DEFINE_MEMBERS(OdDgSysVarPEImpl, OdSysVarPE); inline OdDgHostAppServices* getDgHostAppServices(OdDgDatabase* pDb) { ODA_ASSERT_ONCE(pDb); if (!pDb) return NULL; OdDgHostAppServices* pServices = pDb->appServices(); return pServices; } bool OdDgSysVarPEImpl::getNames(OdRxObject* pRxObject, OdStringArray& names, bool) // bSkipHidden = true { OdDgDatabasePtr pDb = OdDgDatabase::cast(pRxObject); #define REGVAR_DEF(type, name, def_val, unused4, unused5) \ names.push_back(OD_T(#name)); #define REGVAR_DEF_ARRAY(type, name, unused3, unused4, unused5) \ if (!pDb.isNull()) \ { \ type val; \ getDgHostAppServices(pDb)->get##name(val); \ int num = val.size(); \ if (!num) \ num++; \ for (int index = 0; index < num; index++) \ { \ OdString sName; \ sName.format(OD_T("%ls[%d]"), OD_T(#name), index); \ names.push_back(sName); \ } \ } #include "DgRegVarDefs.h" #undef REGVAR_DEF_ARRAY #undef REGVAR_DEF return true; } static OdString OdString_toOdString(int index, const OdString& val, OdSysVarType& typeRb) { ODA_ASSERT_ONCE(!index); typeRb = kRtString; return val; } static OdString OdStringArray_toOdString(int index, const OdStringArray& val, OdSysVarType& typeRb) { ODA_ASSERT_ONCE(index >= 0); typeRb = kRtString; OdString sValue; if (index >= 0 && index < (int) val.size()) sValue = val.getAt(index); return sValue; } static OdString ODTBOOL_toOdString(int index, bool val, OdSysVarType& typeRb) { ODA_ASSERT_ONCE(!index); typeRb = kRtBool; return val ? OD_T("true") : OD_T("false"); } static OdString OdInt16_toOdString(int index, OdInt16 val, OdSysVarType& typeRb) { ODA_ASSERT_ONCE(!index); typeRb = kRtInt16; OdString sValue; sValue.format(OD_T("%d"), val); return sValue; } static OdString OdUInt32_toOdString(int index, OdUInt32 val, OdSysVarType& typeRb) { ODA_ASSERT_ONCE(!index); typeRb = kRtInt32; OdString sValue; sValue.format(OD_T("%d"), val); return sValue; } typedef OdString (*TGetFunc)(OdDgDatabase* pDb, int index, OdSysVarType& typeRb); #define REGVAR_DEF(type, name, def_val, unused4, unused5) \ static OdString get_##name(OdDgDatabase* pDb, int index, OdSysVarType& typeRb) \ { \ type val = getDgHostAppServices(pDb)->get##name(); \ return type##_toOdString(index, val, typeRb); \ } #define REGVAR_DEF_ARRAY(type, name, unused3, unused4, unused5) \ static OdString get_##name(OdDgDatabase* pDb, int index, OdSysVarType& typeRb) \ { \ type val; \ getDgHostAppServices(pDb)->get##name(val); \ return type##_toOdString(index, val, typeRb); \ } #include "DgRegVarDefs.h" #undef REGVAR_DEF_ARRAY #undef REGVAR_DEF static std::map& mapGetFuncs() { static std::map s_mapGetFuncs; if (s_mapGetFuncs.empty()) { #define REGVAR_DEF(type, name, def_val, unused4, unused5) \ s_mapGetFuncs[OD_T(#name)] = get_##name; #define REGVAR_DEF_ARRAY(type, name, unused3, unused4, unused5) \ REGVAR_DEF(type, name, unused3, unused4, unused5) #include "DgRegVarDefs.h" #undef REGVAR_DEF_ARRAY #undef REGVAR_DEF } return s_mapGetFuncs; } static int extractIndex(OdString& sName) { sName.makeUpper(); int index = 0; // default int pos = sName.find(__OD_T('[')); if (pos < 0) pos = sName.find(__OD_T('(')); if (pos > 0) { OdString sIndex = sName.mid(pos + 1); sName = sName.left(pos); pos = sIndex.find(__OD_T(']')); if (pos < 0) pos = sIndex.find(__OD_T(')')); if (pos > 0) sIndex = sIndex.left(pos); index = odStrToInt(sIndex.c_str()); } return index; } OdString OdDgSysVarPEImpl::valueToString(OdRxObject* pRxObject, const OdString& csName, OdSysVarType* pRbType, // = NULL bool* pbExist) // = NULL { if (pbExist) *pbExist = false; if (pRbType) *pRbType = kRtNone; OdString sName = csName; int index = extractIndex(sName); OdDgDatabasePtr pDb = OdDgDatabase::cast(pRxObject); ODA_ASSERT_ONCE(!sName.isEmpty() && !pDb.isNull()); if (sName.isEmpty() || pDb.isNull()) return OdString::kEmpty; std::map::iterator itr = mapGetFuncs().find(sName); if (itr == mapGetFuncs().end()) return OdString::kEmpty; // way for APP variables TGetFunc func = itr->second; OdSysVarType typeRb = kRtString; OdString sValue = (*func)(pDb, index, typeRb); if (pRbType) *pRbType = typeRb; if (pbExist) *pbExist = true; return sValue; } bool OdDgSysVarPEImpl::isEditable(OdRxObject* pRxObject, const OdString& csName, bool* pbExist) // = NULL { if (pbExist) *pbExist = false; OdString sName = csName; int index = extractIndex(sName); OdDgDatabasePtr pDb = OdDgDatabase::cast(pRxObject); ODA_ASSERT_ONCE(!sName.isEmpty() && !pDb.isNull()); if (sName.isEmpty() || pDb.isNull()) return false; std::map::iterator itr = mapGetFuncs().find(sName); if (itr == mapGetFuncs().end()) return false; // way for APP variables if (index) { TGetFunc func = itr->second; OdSysVarType typeRb = kRtString; OdString sValue = (*func)(pDb, index - 1, typeRb); if (sValue.isEmpty()) return false; } if (pbExist) *pbExist = true; return true; } typedef bool (*TSetFunc)(OdDgDatabase* pDb, int index, const OdString& sValue); static bool OdString_toODTBOOL(int index, OdString sValue, OdSysVarType& typeRb) { ODA_ASSERT_ONCE(!index); if (sValue.isEmpty()) throw OdEdEmptyInput(); typeRb = kRtBool; sValue.makeLower().trimLeft().trimRight(); bool val = false; if (sValue == OD_T("true")) val = true; else if (!sValue.isEmpty() && sValue != OD_T("false")&& odStrToInt(sValue) != 0) val = true; return val; } static OdInt16 OdString_toOdInt16(int index, OdString sValue, OdSysVarType& typeRb) { ODA_ASSERT_ONCE(!index); if (sValue.isEmpty()) throw OdEdEmptyInput(); typeRb = kRtInt16; OdInt16 val = (OdInt16) odStrToInt(sValue); return val; } static OdUInt32 OdString_toOdUInt32(int index, OdString sValue, OdSysVarType& typeRb) { ODA_ASSERT_ONCE(!index); if (sValue.isEmpty()) throw OdEdEmptyInput(); typeRb = kRtInt32; OdUInt32 val = odStrToInt(sValue); return val; } static bool OdString_toOdStringArray(int index, OdString sValue, OdStringArray& val) { ODA_ASSERT_ONCE(index >= 0); if (index < 0 || index > (int) val.size()) return false; if (index == (int) val.size()) val.push_back(sValue); else val.setAt(index, sValue); if (sValue.isEmpty()) { while (val.remove(OdString::kEmpty)) ; } return true; } #define REGVAR_DEF(type, name, def_val, unused4, unused5) \ static bool set_##name(OdDgDatabase* pDb, int index, const OdString& sValue) \ { \ OdSysVarType typeRb = kRtNone; \ type val = OdString_to##type(index, sValue, typeRb); \ if (val == getDgHostAppServices(pDb)->get##name()) \ return false; \ getDgHostAppServices(pDb)->set##name(val); \ return true; \ } #define REGVAR_DEF_ARRAY(type, name, unused3, unused4, unused5) \ static bool set_##name(OdDgDatabase* pDb, int index, const OdString& sValue) \ { \ type val; \ getDgHostAppServices(pDb)->get##name(val); \ if (!OdString_to##type(index, sValue, val)) \ return false; \ getDgHostAppServices(pDb)->set##name(val); \ return true; \ } #include "DgRegVarDefs.h" #undef REGVAR_DEF_ARRAY #undef REGVAR_DEF static std::map& mapSetFuncs() { static std::map s_mapSetFuncs; if (s_mapSetFuncs.empty()) { #define REGVAR_DEF(type, name, def_val, unused4, unused5) \ s_mapSetFuncs[OD_T(#name)] = set_##name; #define REGVAR_DEF_ARRAY(type, name, unused3, unused4, unused5) \ REGVAR_DEF(type, name, unused3, unused4, unused5) #include "DgRegVarDefs.h" #undef REGVAR_DEF_ARRAY #undef REGVAR_DEF } return s_mapSetFuncs; } bool OdDgSysVarPEImpl::editValue(OdEdCommandContext* pCmdCtx, const OdString& csName, bool* pbExist) // = NULL { if (pbExist) *pbExist = false; OdString sName = csName; int index = extractIndex(sName); ODA_ASSERT_ONCE(pCmdCtx && !sName.isEmpty()); if (!pCmdCtx || sName.isEmpty()) return false; OdDgDatabasePtr pDb = OdDgDatabase::cast(pCmdCtx->baseDatabase()); ODA_ASSERT_ONCE(!pDb.isNull()); if (pDb.isNull()) return false; std::map::iterator itr = mapSetFuncs().find(sName); if (itr == mapSetFuncs().end()) return false; // way for APP variables TSetFunc func = itr->second; if (pbExist) *pbExist = true; OdSysVarType typeRb = kRtNone; OdString sValue = valueToString(pCmdCtx->baseDatabase(), csName, &typeRb); OdString sPrompt; sPrompt.format(OD_T("Enter new value for %ls <%ls>:"), OdString(csName).makeUpper().c_str(), sValue.c_str()); try { switch (typeRb) { case kRtBool: sPrompt.format(OD_T("Enter new value for %ls [true/false]<%ls>:"), OdString(csName).makeUpper().c_str(), sValue.c_str()); sValue = pCmdCtx->userIO()->getString(sPrompt, OdEd::kInpThrowEmpty, sValue, OD_T("true false")); break; case kRtInt16: case kRtInt32: sValue = pCmdCtx->userIO()->getString(sPrompt, OdEd::kInpThrowEmpty, sValue, sValue); break; default: ODA_FAIL_ONCE(); // TODO case kRtString: sValue = pCmdCtx->userIO()->getString(sPrompt, OdEd::kGstAllowSpaces|OdEd::kInpThrowEmpty, sValue, sValue); break; } sValue.trimRight(); bool bRes = (*func)(pDb, index, sValue); return bRes; } catch(const OdEdKeyword&) { } catch(const OdEdEmptyInput&) { } catch(const OdEdCancel&) { } return false; } /////////////////////////////////////////////////////////////////////////////// static bool s_bOdDgSysVarPEinitialized = false; static bool s_bUnlinkedWithOdSysVarPE = false; static bool s_bUnlinkedWithPropServices = false; static bool s_bUnlinkedWithExAppServices = false; void initOdDgSysVarPE() { static OdStaticRxObject s_DgSysVarPE; if (s_bOdDgSysVarPEinitialized) return; s_bOdDgSysVarPEinitialized = true; OdRxDictionary* pClassDict = ::odrxClassDictionary().get(); s_bUnlinkedWithOdSysVarPE = (!OdSysVarPE::g_pDesc); if (s_bUnlinkedWithOdSysVarPE) { // We have duplicated definition of g_pDesc, desc(), isA() and queryX(...) // via ODRX_NO_CONS_DEFINE_MEMBERS(OdSysVarPE, OdRxObject); // (to prevent inconvenient linking with OdaQtConsole) #if !defined(ODA_SYS_VAR_PE_UNLINKED_RXINIT) ODA_FAIL_ONCE(); #endif // see also newOdRxClass OdRxClass* pOdSysVarPEClass = OdRxClass::cast(pClassDict->getAt(OD_T("OdSysVarPE"))).get(); ODA_ASSERT_ONCE(pOdSysVarPEClass); OdSysVarPE::g_pDesc = pOdSysVarPEClass; } OdDgSysVarPEImpl::rxInit(); OdDgDatabase::desc()->addX(OdSysVarPE::desc(), &s_DgSysVarPE); s_bUnlinkedWithPropServices = (!OdPropServices::g_pDesc); if (s_bUnlinkedWithPropServices) { // We have duplicated definition of g_pDesc, desc(), isA() and queryX(...) // via ODRX_NO_CONS_DEFINE_MEMBERS(OdPropServices, OdRxObject); // (to prevent impossible linking with OdaQtApp) #if !defined(ODA_PROP_SERVICES_UNLINKED_RXINIT) ODA_FAIL_ONCE(); #endif // see also newOdRxClass OdRxClass* pOdPropServicesClass = OdRxClass::cast(pClassDict->getAt(OD_T("OdPropServices"))).get(); //via OdaCloudServer //ODA_ASSERT_ONCE(pOdPropServicesClass); OdPropServices::g_pDesc = pOdPropServicesClass; } s_bUnlinkedWithExAppServices = (!ExAppServices::g_pDesc); if (s_bUnlinkedWithExAppServices) { // We have duplicated definition of g_pDesc, desc(), isA() and queryX(...) // via ODRX_NO_CONS_DEFINE_MEMBERS(ExAppServices, OdRxObject); // (to prevent impossible linking with OdaQtApp) #if !defined(ODA_EX_APP_SERVICES_UNLINKED_RXINIT) ODA_FAIL_ONCE(); #endif // see also newOdRxClass OdRxClass* pExAppServicesClass = OdRxClass::cast(pClassDict->getAt(OD_T("ExAppServices"))).get(); //via OdaCloudServer //ODA_ASSERT_ONCE(pExAppServicesClass); ExAppServices::g_pDesc = pExAppServicesClass; } } void uninitOdDgSysVarPE() { if (!s_bOdDgSysVarPEinitialized) return; s_bOdDgSysVarPEinitialized = false; if (s_bUnlinkedWithExAppServices) ExAppServices::g_pDesc = NULL; if (s_bUnlinkedWithPropServices) OdPropServices::g_pDesc = NULL; OdDgDatabase::desc()->delX(OdSysVarPE::desc()); OdDgSysVarPEImpl::rxUninit(); if (s_bUnlinkedWithOdSysVarPE) OdSysVarPE::g_pDesc = NULL; }