/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, 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-2025 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 "OdaCommon.h" #include "OdOptical.h" #include "OdOpticalCdaProperties.h" #include "DbMText.h" #include "RxObjectImpl.h" #include "StaticRxObject.h" #include "RxAttribute.h" #include "RxCategory.h" #include "RxValueTypeUtil.h" FIRSTDLL_EXPORT void odrxSetMemberConstructor(OdRxClass* pClass, OdRxMemberCollectionConstructorPtr pc, void* data = 0); // out of header //---------------------------------------------------------------------------------------------------------------------- // OdFdOpticalFieldData::SPARQCode //---------------------------------------------------------------------------------------------------------------------- template<> OPTICAL_EXPORT bool OdRxEnumType::subEqualTo(const void* a, const void* b) const { return *(OdFdOpticalFieldData::SPARQCode*)a == *(OdFdOpticalFieldData::SPARQCode*)b; } template<> OPTICAL_EXPORT OdString OdRxEnumType::subToString(const void* instance, OdRxValueType::StringFormat) const { if (!instance) throw OdError(L"Empty value instance"); // it actually returns numeric value in ARX, idk the reason return OdString().format(L"%d", (int)*(OdFdOpticalFieldData::SPARQCode*)instance); } static OdRxEnumType* s_gSPARQCode = 0; template<> OPTICAL_EXPORT const OdRxValueType& OdRxValueType::Desc::value() throw() { if (!s_gSPARQCode) { static OdMutex m; TD_AUTOLOCK(m); if (!s_gSPARQCode) { s_gSPARQCode = new OdRxEnumType(L"OdFdOpticalFieldData::SPARQCode", 0); ODRX_APPEND_VALUE_TAG(s_gSPARQCode, OdFdOpticalFieldData::k_None); ODRX_APPEND_VALUE_TAG(s_gSPARQCode, OdFdOpticalFieldData::k_Email); ODRX_APPEND_VALUE_TAG(s_gSPARQCode, OdFdOpticalFieldData::k_Telephone); ODRX_APPEND_VALUE_TAG(s_gSPARQCode, OdFdOpticalFieldData::k_vCard); ODRX_APPEND_VALUE_TAG(s_gSPARQCode, OdFdOpticalFieldData::k_mCard); ODRX_APPEND_VALUE_TAG(s_gSPARQCode, OdFdOpticalFieldData::k_ShortMessageService); ODRX_APPEND_VALUE_TAG(s_gSPARQCode, OdFdOpticalFieldData::k_MultimediaMessageService); ODRX_APPEND_VALUE_TAG(s_gSPARQCode, OdFdOpticalFieldData::k_Geolocation); } } return *s_gSPARQCode; } template<> OPTICAL_EXPORT OdRxValue::OdRxValue(OdFdOpticalFieldData::SPARQCode const& val) throw() : m_type(OdRxValueType::Desc::value()) { initBlittable(&val, sizeof(OdFdOpticalFieldData::SPARQCode)); } template<> OPTICAL_EXPORT void OdRxValueType::Desc::del() { if (s_gSPARQCode) { ::odrxClassDictionary()->remove(L"OdFdOpticalFieldData::SPARQCode"); delete s_gSPARQCode; s_gSPARQCode = nullptr; } } //---------------------------------------------------------------------------------------------------------------------- // OdFdOpticalFieldDataPropertyFacetProvider //---------------------------------------------------------------------------------------------------------------------- OdRxFacetProviderPtr OdFdOpticalFieldDataPropertyFacetProvider::instance; OdRxFacetProviderPtr OdFdOpticalFieldDataPropertyFacetProvider::createObject() { OdRxFacetProviderPtr res = OdRxObjectImpl::createObject(); instance = res; return res; } void OdFdOpticalFieldDataPropertyFacetProvider::addProvider() // use as initCDAProperties() { createObject(); OdRxMemberQueryEngine::theEngine()->addFacetProvider(instance); } void OdFdOpticalFieldDataPropertyFacetProvider::removeProvider() // use as uninitCDAProperties() { OdRxMemberQueryEngine::theEngine()->removeFacetProvider(instance); OdRxValueType::Desc::del(); instance = nullptr; } void OdFdOpticalFieldDataPropertyFacetProvider::getFacets(const OdRxObject* pO, const OdRxMemberQueryContext*, OdArray& facets) { OdDbMText* pMText = OdDbMText::cast(pO).get(); if (!pMText || !pMText->isDBRO()) // ACAD shows these properties if optical data missing too (as disabled) return; OdRxClassPtr pPropertyFacet = OdFdOpticalFieldDataPropertyFacet::createObject(); ::odrxSetMemberConstructor(pPropertyFacet, &OdFdOpticalFieldDataPropertyFacet::makeMembers, (void*) pO); facets.append(pPropertyFacet); } //---------------------------------------------------------------------------------------------------------------------- // OdFdOpticalFieldDataProperty //---------------------------------------------------------------------------------------------------------------------- struct OdFdOpticalFieldDataProperty : OdRxProperty { enum OdFdOpticalFieldDataPropertyIndex { idxScannable, idxHint, idxScale } m_index; static OdRxMemberPtr createObject(const OdRxClass* owner, enum OdFdOpticalFieldDataPropertyIndex index) { OdRxMemberPtr pTextCat = OdRxCategory::rootCategory()->findDescendant(L"Text"); if (pTextCat.isNull()) pTextCat = OdRxCategory::createObject(L"Text", OdRxCategory::rootCategory()); OdRxMemberPtr pRes = OdRxObjectImpl::createObject(); OdFdOpticalFieldDataProperty* pProperty = (OdFdOpticalFieldDataProperty*)pRes.get(); pProperty->m_index = index; pProperty->attributes().add(OdRxUiPlacementAttribute::createObject(L"Text", 2)); switch (index) { case idxScannable: pProperty->init(L"Optically Scannable", &OdRxValueType::Desc::value(), owner); pProperty->attributes().add(OdRxDescriptionAttribute::createObject(L"Draw the text as an optically scannable image")); //pProperty->attributes().add(OdRxCOMAttribute::createObject(L"OpticallyScannable")); //pProperty->attributes().add(OdRxLocalizedNameAttribute::createObject(L"...")); break; case idxHint: pProperty->init(L"Optical Hint", &OdRxValueType::Desc::value(), owner); pProperty->attributes().add(OdRxDescriptionAttribute::createObject(L"Specifies a SPARQCode hint for the image")); break; case idxScale: pProperty->init(L"Optical Image Size", &OdRxValueType::Desc::value(), owner); pProperty->attributes().add(OdRxDescriptionAttribute::createObject(L"The size of the optically scannable image")); break; default: ODA_FAIL_ONCE(); } return pRes; } virtual OdResult subGetValue(const OdRxObject* pO, OdRxValue& value) const ODRX_OVERRIDE { OdDbObjectId idFieldData = OdFdOpticalFieldData::opticalDataForObject(OdDbObject::cast(pO).get()); OdFdOpticalFieldDataPtr pFieldData = OdFdOpticalFieldData::cast(idFieldData.openObject(OdDb::kForRead)); if (pFieldData.isNull()) { // ACAD shows these properties if optical data missing too (as disabled) OdDbMText* pMText = OdDbMText::cast(pO).get(); if (!pMText || !pMText->isDBRO()) return eNotApplicable; switch (m_index) { case idxScannable: value = false; break; case idxHint: value = OdFdOpticalFieldData::k_None; break; case idxScale: value = 1.0; break; default: ODA_FAIL_ONCE(); return eNotApplicable; } return eOk; } switch (m_index) { case idxScannable: value = static_cast(pFieldData->isEnabled()); break; case idxHint: value = static_cast(pFieldData->SPARQCodeHint()); break; case idxScale: value = static_cast(pFieldData->size()); break; default: ODA_FAIL_ONCE(); return eNotApplicable; } return eOk; } virtual OdResult subSetValue(OdRxObject* pO, const OdRxValue& value) const ODRX_OVERRIDE { OdDbObject* pObj = OdDbObject::cast(pO).get(); OdDbObjectId idFieldData = OdFdOpticalFieldData::opticalDataForObject(pObj); if (idFieldData.isNull()) idFieldData = OdFdOpticalFieldData::createOpticalDataForObject(pObj); // ACAD shows these properties if optical data missing too (as disabled) OdFdOpticalFieldDataPtr pFieldData = OdFdOpticalFieldData::cast(idFieldData.openObject(OdDb::kForWrite)); ODA_ASSERT_ONCE(pFieldData.get()); if (pFieldData.isNull()) return eNotApplicable; switch (m_index) { case idxScannable: { bool val; if (!(value >> val)) return eInvalidInput; if (val == pFieldData->isEnabled()) break; pFieldData->setEnabled(val); break; } case idxHint: { OdFdOpticalFieldData::SPARQCode val; if (!(value >> val)) return eInvalidInput; // commented as way to normalization // if (val == pFieldData->SPARQCodeHint()) break; return pFieldData->setSPARQCodeHint(val); } case idxScale: { double val; if (!(value >> val)) return eInvalidInput; // commented as way to normalization // if (val == pFieldData->size()) break; return pFieldData->setSize(val); } default: ODA_FAIL_ONCE(); return eNotApplicable; } return eOk; } }; //---------------------------------------------------------------------------------------------------------------------- // OdFdOpticalFieldDataPropertyFacet //---------------------------------------------------------------------------------------------------------------------- void OdFdOpticalFieldDataPropertyFacet::makeMembers(OdRxMemberCollectionBuilder& collectionBuilder, void* ODA_ASSERT_VAR(data)) { ODA_ASSERT_VAR(const OdRxObject* pO = static_cast(data);) ODA_ASSERT_VAR(OdDbMText* pMText = OdDbMText::cast(pO).get();) ODA_ASSERT_ONCE(pMText && pMText->isDBRO()); // ACAD shows these properties if optical data missing too (as disabled) //static OdArray properties; OdRxMemberPtr pMember = OdFdOpticalFieldDataProperty::createObject( collectionBuilder.owner(), OdFdOpticalFieldDataProperty::idxScannable); if (pMember.get()) collectionBuilder.add(pMember); pMember = OdFdOpticalFieldDataProperty::createObject( collectionBuilder.owner(), OdFdOpticalFieldDataProperty::idxHint); if (pMember.get()) collectionBuilder.add(pMember); pMember = OdFdOpticalFieldDataProperty::createObject( collectionBuilder.owner(), OdFdOpticalFieldDataProperty::idxScale); if (pMember.get()) collectionBuilder.add(pMember); }