String-based wrappers are the main mechanism for implementing custom object properties for ODA Drawings Explorer (ODE). In particular, Common Data Access (CDA) support for ODE is implemented through the OdDbXmlPropCdaBased
string XML wrapper. For the implementation, see Drawing/Examples/Qt/OdaQtPropSystem/DbXmlPropSources.cpp
.
Full support for custom entities should be based on CDA, but this approach is labor-intensive. However, when you cannot look at or change several properties in ODE, it is much easier to start with a string wrapper.
A special example of creating a wrapper for the Smiley custom entity is provided. To run this sample, add the built OdaQtSmileyProp.tx
file to the Startup Suite using the APPLOAD
command. "Qt" is included in the name only for consistency and to indicate that the module should be loaded from ODE; Qt is not used in this module.
Adding new custom wrappers is fairly easy to implement through the use of OdPropServices. These services are only implemented in ODE and are available to loaded modules. These services are not part of Kernel SDK. Therefore, linking with them is problematic. To avoid the need for linking, add the following code to your module:
ODRX_NO_CONS_DEFINE_MEMBERS(OdPropServices, OdRxObject);
void ...::initApp()
{
OdPropServices::g_pDesc = OdRxClass::cast(::odrxClassDictionary()->getAt(OD_PROP_SERVICES)).get();
}
void ...::uninitApp()
{
OdPropServices::g_pDesc = NULL;
}
Then, you can use the propServices()
function to get services if the module is loaded into ODE:
static OdPropServices* propServices()
{
OdPropServicesPtr pPropServices = ::odrxSysRegistry()->getAt(OD_PROP_SERVICES);
ODA_ASSERT_ONCE(!pPropServices.isNull()); // is loaded out of ODE
return pPropServices.get();
}
All string wrapper classes are inherited from the base OdPropBase
class. It is enough to overload getPropertyValues()
with your own description of additional properties to see them after registering the wrapper.
As a key, for registering or unregistering a string wrapper, use desc()->name()
of your custom entity class. If the desc()
method of your custom class is not available by linking, you can use its string value directly, as in the smiley example:
if (OdPropServices* pPropSrv = propServices())
pPropSrv->registerXmlProp(L"AsdkSmiley",
&OdRxObjectImpl::createObject);
The method used for getting the properties works in special contexts. You can add a category to the original context and get the category context, and then add different properties to it. Upon return from the method, context destructors form a string XML description of the properties with their values and other attributes.
virtual bool getPropertyValues(OdPropContext& ctx)
{
OdDbEntityPtr pEnt = object();
AsdkSmiley* pSmiley = static_cast(pEnt.get());
OdPropContext ctxSmiley = ctx.addCategory(L"Smiley");
ctxSmiley.addProperty(L"radius", pSmiley->radius(), tDistance)
.comment(L"pop-up text appearing while hovering over the property name"); //.readOnly();
...
return true;
}
To support editing, overload the following method:
virtual bool setPropertyValue(const OdString& sPath, const OdString& sValue, Action& action)
{
if (sPath == L"Smiley/radius")
{
OdDbEntityPtr pEnt = object(true); // enabled to write
AsdkSmiley* pSmiley = static_cast(pEnt.get());
double dRadius = toDistance(sValue);
pSmiley->setRadius(dRadius);
return true;
}
return false;
}
For properties with the tCombo type, also overload the getPropertyPossibleValues()
method, returning a list of valid text values for the sPath
key from category and property names.
Additionally, you can overload the name of the entity in the combo box of the selected entities.
virtual bool overrideClassName(OdString& sClassName) const
{
sClassName = L"Smiley Custom Entity";
return true;
}
Copyright © 2002 – 2022. Open Design Alliance. All rights reserved.
|