/** * @file XTPMarkupObject.cpp * * @copyright * (c) 1998-2025 Codejock Software, All Rights Reserved. * * This source file is the property of Codejock Software and must not be * redistributed by any means without the explicit written permission of * Codejock Software. * * The use of this source code is governed by the terms and conditions specified * in the Toolkit Pro license agreement. Codejock Software grants you, as a * single software developer, the limited right to use this software on one * computer only. * * Contact Information: * support@codejock.com * http://www.codejock.com * */ #include "stdafx.h" #include "Common/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPMacros.h" #include "Common/XTPFramework.h" #include "Common/XTPVc80Helpers.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSynchro.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPXMLHelpers.h" #include "Common/XTPMathUtils.h" #include #include "Markup/XTPMarkupTools.h" #include "Markup/XTPMarkupObject.h" #include "Markup/XTPMarkupContext.h" #include "Markup/XTPMarkupString.h" #include "Markup/XTPMarkupBuilder.h" #include "Markup/XTPMarkupStyle.h" #include "Markup/Extensions/XTPMarkupExtension.h" #include "Markup/XTPMarkupIIDs.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # undef THIS_FILE static char THIS_FILE[] = __FILE__; # define new DEBUG_NEW #endif #ifndef _XTP_DISABLE_COMPAREELEMENTS_SPECIALIZATION template<> AFX_INLINE BOOL AFXAPI CompareElements(const LPCWSTR* pElement1, const LPCWSTR* pElement2) { return wcscmp(*pElement1, *pElement2) == 0; } #endif /////////////////////////////////////////////////////////////////////////////// // CXTPMarkupObjectAttachedPropertyDispCollection class CXTPMarkupObjectAttachedPropertyDispCollection { static const DISPID m_firstDispId; struct Data { Data() { memset(this, 0, sizeof(*this)); } Data(LPWSTR lpName, DISPID dispId, LPVOID pData) : lpName(lpName) , dispId(dispId) { u.pData = pData; } LPWSTR lpName; DISPID dispId; union { LPVOID pData; CXTPMarkupType* pType; CXTPMarkupDependencyProperty* pProperty; } u; }; public: CXTPMarkupObjectAttachedPropertyDispCollection() : m_nextDispId(m_firstDispId) { } ~CXTPMarkupObjectAttachedPropertyDispCollection() { POSITION pos = m_map.GetStartPosition(); while (NULL != pos) { UINT nKey = 0; CList* pList = NULL; m_map.GetNextAssoc(pos, nKey, pList); if (NULL != pList) { POSITION lpos = pList->GetHeadPosition(); while (NULL != lpos) { Data& data = pList->GetNext(lpos); if (NULL != data.lpName) free(data.lpName); } delete pList; } } } BOOL Lookup(DISPID id, LPCWSTR* ppName = NULL, LPVOID* ppData = NULL) const { const Data* pd = NULL; if (!m_ids.Lookup(id, pd)) return FALSE; if (NULL != ppName) *ppName = pd->lpName; if (NULL != ppData) *ppData = pd->u.pData; return TRUE; } DISPID OnGetDispID(LPCWSTR lpName, LPVOID pData = NULL) { const Data* p = GetData(lpName, pData); if (NULL == p) return DISPID_UNKNOWN; return p->dispId; } private: const Data* GetData(LPCWSTR lpName, LPVOID pData) { _ASSERTE(NULL != lpName); UINT nKey = HashKey(lpName); CList*& pList = m_map[nKey]; if (NULL != pList) { POSITION pos = pList->GetHeadPosition(); while (NULL != pos) { Data& data = pList->GetNext(pos); if (0 == wcscmp(data.lpName, lpName)) return &data; } } else { pList = new CList(); } LPWSTR lpDupName = _wcsdup(lpName); if (NULL == lpDupName) { delete pList; pList = NULL; return NULL; } Data data(lpDupName, m_nextDispId++, pData); pList->AddTail(data); Data* pd = &pList->GetTail(); m_ids[pd->dispId] = pd; return pd; } private: DISPID m_nextDispId; CMap*, CList*> m_map; CMap m_ids; }; const DISPID CXTPMarkupObjectAttachedPropertyDispCollection::m_firstDispId = 0x10000000; /////////////////////////////////////////////////////////////////////////////// // CXTPMarkupPropertyChangedEventArgs CXTPMarkupPropertyChangedEventArgs::CXTPMarkupPropertyChangedEventArgs( CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pOldValue, CXTPMarkupObject* pNewValue) { m_pProperty = pProperty; m_pOldValue = pOldValue; m_pNewValue = pNewValue; } struct CXTPMarkupFromNameKey { public: CXTPMarkupFromNameKey(LPCWSTR lpszName = NULL, CXTPMarkupType* pOwnerType = NULL) { m_lpszName = lpszName; m_pOwnerType = pOwnerType; } BOOL operator==(const CXTPMarkupFromNameKey& key) const { return (NULL != m_pOwnerType ? m_pOwnerType->IsEqualTo(key.m_pOwnerType) : NULL == key.m_pOwnerType) && (m_lpszName == key.m_lpszName || wcscmp(m_lpszName, key.m_lpszName) == 0); } LPCWSTR m_lpszName; CXTPMarkupType* m_pOwnerType; }; template<> AFX_INLINE UINT AFXAPI HashKey(CXTPMarkupFromNameKey& key) { UINT nameHash = HashKey(key.m_lpszName); UINT typeHash = HashKey(NULL != key.m_pOwnerType ? key.m_pOwnerType->GetHashKey() : NULL); return (nameHash * typeHash) + (nameHash ^ typeHash); } /////////////////////////////////////////////////////////////////////////////// // CXTPMarkupPropertyFromNameMap class CXTPMarkupPropertyFromNameMap : public CMap { public: CXTPMarkupPropertyFromNameMap(); ~CXTPMarkupPropertyFromNameMap(); }; CXTPMarkupPropertyFromNameMap::CXTPMarkupPropertyFromNameMap() { } CXTPMarkupPropertyFromNameMap::~CXTPMarkupPropertyFromNameMap() { POSITION pos = GetStartPosition(); while (pos) { CXTPMarkupFromNameKey key; CXTPMarkupDependencyProperty* dp; GetNextAssoc(pos, key, dp); dp->Release(); } RemoveAll(); } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupPropertyMetadata CXTPMarkupPropertyMetadata::CXTPMarkupPropertyMetadata(CXTPMarkupObject* pDefaultValue, DWORD dwFlags) { m_pDefaultValue = pDefaultValue; m_pConverter = NULL; m_dwFlags = dwFlags; m_pPropertyChanged = NULL; } CXTPMarkupPropertyMetadata::CXTPMarkupPropertyMetadata(CXTPMarkupObject* pDefaultValue, PFNCONVERTFROM pConverter, DWORD dwFlags) { m_pDefaultValue = pDefaultValue; m_pConverter = pConverter; m_dwFlags = dwFlags; m_pPropertyChanged = NULL; } CXTPMarkupPropertyMetadata::CXTPMarkupPropertyMetadata(CXTPMarkupObject* pDefaultValue, PFNPROPERTYCHANGED pPropertyChanged, DWORD dwFlags) { m_pDefaultValue = pDefaultValue; m_pConverter = NULL; m_dwFlags = dwFlags; m_pPropertyChanged = pPropertyChanged; } CXTPMarkupPropertyMetadata::CXTPMarkupPropertyMetadata(CXTPMarkupObject* pDefaultValue, PFNCONVERTFROM pConverter, PFNPROPERTYCHANGED pPropertyChanged, DWORD dwFlags) { m_pDefaultValue = pDefaultValue; m_pConverter = pConverter; m_dwFlags = dwFlags; m_pPropertyChanged = pPropertyChanged; } CXTPMarkupPropertyMetadata::~CXTPMarkupPropertyMetadata() { if (m_pDefaultValue) { MARKUP_RELEASE(m_pDefaultValue); } } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupDependencyProperty int CXTPMarkupDependencyProperty::s_nCount = 0; IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupDependencyProperty, CXTPMarkupObject); CXTPMarkupPropertyFromNameMap* CXTPMarkupDependencyProperty::GetPropertyMap() { return &CXTPSingleton::Instance(); } void CXTPMarkupDependencyProperty::RegisterMarkupClass() { } CXTPMarkupDependencyProperty::CXTPMarkupDependencyProperty() : CXTPMarkupObject(flagNoCom) { m_lpszName = 0; m_pPropetyType = 0; m_pOwnerType = 0; m_bAttached = FALSE; m_pMetadata = NULL; m_nIndex = -1; } CXTPMarkupDependencyProperty::~CXTPMarkupDependencyProperty() { SAFE_DELETE(m_pMetadata); } CXTPMarkupDependencyProperty* AFX_CDECL CXTPMarkupDependencyProperty::RegisterCommon( CXTPMarkupDependencyProperty* dp, LPCWSTR lpszName, CXTPMarkupType* pPropetyType, CXTPMarkupType* pOwnerType, BOOL bAttached) { CXTPMarkupFromNameKey key(lpszName, pOwnerType); dp->m_lpszName = lpszName; dp->m_pPropetyType = pPropetyType; dp->m_pOwnerType = pOwnerType; dp->m_bAttached = bAttached; CXTPMarkupPropertyFromNameMap* pPropertyFromNameMap = GetPropertyMap(); if (!dp->IsEvent()) { dp->m_nIndex = s_nCount++; } pPropertyFromNameMap->SetAt(key, dp); return dp; } CXTPMarkupDependencyProperty* AFX_CDECL CXTPMarkupDependencyProperty::RegisterAttached( LPCWSTR lpszName, CXTPMarkupType* pPropetyType, CXTPMarkupType* pOwnerType, CXTPMarkupPropertyMetadata* pMetadata) { CXTPMarkupDependencyProperty* dp = RegisterCommon(new CXTPMarkupDependencyProperty(), lpszName, pPropetyType, pOwnerType, TRUE); dp->m_pMetadata = pMetadata; return dp; } CXTPMarkupDependencyProperty* AFX_CDECL CXTPMarkupDependencyProperty::Register( LPCWSTR lpszName, CXTPMarkupType* pPropetyType, CXTPMarkupType* pOwnerType, CXTPMarkupPropertyMetadata* pMetadata) { CXTPMarkupDependencyProperty* dp = RegisterCommon(new CXTPMarkupDependencyProperty(), lpszName, pPropetyType, pOwnerType, FALSE); dp->m_pMetadata = pMetadata; return dp; } CXTPMarkupDependencyProperty* CXTPMarkupDependencyProperty::AddOwner(CXTPMarkupType* pOwnerType) { CXTPMarkupFromNameKey key(m_lpszName, pOwnerType); CXTPMarkupPropertyFromNameMap* pPropertyFromNameMap = GetPropertyMap(); pPropertyFromNameMap->SetAt(key, this); AddRef(); return this; } CXTPMarkupDependencyProperty* CXTPMarkupDependencyProperty::FindProperty(CXTPMarkupType* pRuntimeClass, LPCWSTR lpszAttribute) { if (!lpszAttribute) return NULL; if (lpszAttribute[0] == 'x' && lpszAttribute[1] == ':') lpszAttribute = lpszAttribute + 2; CXTPMarkupPropertyFromNameMap* pMap = CXTPMarkupDependencyProperty::GetPropertyMap(); while (pRuntimeClass != NULL) { CXTPMarkupFromNameKey nameKey(lpszAttribute, pRuntimeClass); CXTPMarkupDependencyProperty* pProperty = NULL; if (pMap->Lookup(nameKey, pProperty)) return pProperty; pRuntimeClass = pRuntimeClass->GetBaseType(); } return NULL; } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupType class CXTPMarkupType::CClassList { public: ~CClassList(); public: typedef CXTPMarkupType*(AFX_CDECL* PFNGetType)(); class CTypeEntry { public: CTypeEntry(); void SetGetType(PFNGetType pfnGetType); CXTPMarkupType* GetType() const; private: PFNGetType m_pfnGetType; }; CTypeEntry* Register(LPCWSTR lpszTag, PFNGetType pfnGetType); CXTPMarkupType* Lookup(LPCWSTR lpszTag); void RegisterAll(); void UnregisterAll(); private: CMap m_namedTypes; CList m_unnamedTypes; friend class CXTPMarkupType; }; CXTPMarkupType::CClassList::CTypeEntry::CTypeEntry() : m_pfnGetType(NULL) { } void CXTPMarkupType::CClassList::CTypeEntry::SetGetType(PFNGetType pfnGetType) { _ASSERTE(NULL != pfnGetType); _ASSERTE(NULL == m_pfnGetType); m_pfnGetType = pfnGetType; } CXTPMarkupType* CXTPMarkupType::CClassList::CTypeEntry::GetType() const { _ASSERTE(NULL != m_pfnGetType); return m_pfnGetType(); } CXTPMarkupType::CClassList::~CClassList() { _ASSERTE(m_namedTypes.IsEmpty()); _ASSERTE(m_unnamedTypes.IsEmpty()); } CXTPMarkupType::CClassList::CTypeEntry* CXTPMarkupType::CClassList::Register(LPCWSTR lpszTag, PFNGetType pfnGetType) { CTypeEntry* pTypeEntry = NULL; CTypeEntry typeEntry; typeEntry.SetGetType(pfnGetType); if (NULL != lpszTag && L'\0' != lpszTag[0]) { _ASSERTE(Lookup(lpszTag) == NULL); m_namedTypes.SetAt(lpszTag, typeEntry); _ASSERTE(Lookup(lpszTag) != NULL); } else { m_unnamedTypes.AddTail(typeEntry); } return pTypeEntry; } void CXTPMarkupType::CClassList::RegisterAll() { POSITION pos = m_namedTypes.GetStartPosition(); while (NULL != pos) { LPCWSTR key = NULL; CClassList::CTypeEntry typeEntry; m_namedTypes.GetNextAssoc(pos, key, typeEntry); CXTPMarkupType* pType = typeEntry.GetType(); pType->Register(); } pos = m_unnamedTypes.GetHeadPosition(); while (NULL != pos) { CXTPMarkupType* pType = m_unnamedTypes.GetNext(pos).GetType(); pType->Register(); } } void CXTPMarkupType::CClassList::UnregisterAll() { POSITION pos = m_unnamedTypes.GetHeadPosition(); while (NULL != pos) { CXTPMarkupType* pType = m_unnamedTypes.GetNext(pos).GetType(); if (NULL != pType) pType->Unregister(); } pos = m_namedTypes.GetStartPosition(); while (NULL != pos) { LPCWSTR key = NULL; CClassList::CTypeEntry typeEntry; m_namedTypes.GetNextAssoc(pos, key, typeEntry); CXTPMarkupType* pType = typeEntry.GetType(); if (NULL != pType) pType->Unregister(); } m_namedTypes.RemoveAll(); m_unnamedTypes.RemoveAll(); } CXTPMarkupType* CXTPMarkupType::CClassList::Lookup(LPCWSTR lpszTag) { _ASSERTE(NULL != lpszTag); CClassList::CTypeEntry typeEntry; if (m_namedTypes.Lookup(lpszTag, typeEntry)) return typeEntry.GetType(); return NULL; } CXTPMarkupType::CClassList* AFX_CDECL CXTPMarkupType::GetClassList() { return &CXTPSingleton::Instance(); } CXTPMarkupType* CXTPMarkupType::LookupTag(LPCWSTR lpszTag) { return GetClassList()->Lookup(lpszTag); } IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupType, CXTPMarkupObject) void CXTPMarkupType::RegisterMarkupClass() { } CXTPMarkupType::CXTPMarkupType() : CXTPMarkupObject(flagNoCom) { m_lpszTag = NULL; m_lpszClassName = NULL; m_pfnCreateObject = NULL; m_pfnGetBaseType = NULL; m_pfnRegisterMarkupClass = NULL; m_pfnUnregisterMarkupClass = NULL; m_bRegister = FALSE; m_pTypeStyle = NULL; } CXTPMarkupType::CXTPMarkupType(LPCWSTR lpszTag, LPCWSTR lpszClassName, PFNCREATEOBJECT pfnCreateObject, PFNGETBASETYPE pfnGetBaseType, PFNREGISTERMARKUPCLASS pfnRegisterMarkupClass /*= NULL*/, PFNREGISTERMARKUPCLASS pfnUnregisterMarkupClass /*= NULL*/) : CXTPMarkupObject(flagNoCom) { m_lpszTag = lpszTag; m_lpszClassName = lpszClassName; m_pfnCreateObject = pfnCreateObject; m_pfnGetBaseType = pfnGetBaseType; m_pfnRegisterMarkupClass = pfnRegisterMarkupClass; m_pfnUnregisterMarkupClass = pfnUnregisterMarkupClass; m_bRegister = FALSE; m_pTypeStyle = NULL; } CXTPMarkupObject* CXTPMarkupType::ConvertFrom(CXTPMarkupBuilder* /*pBuilder*/, CXTPMarkupObject* pObject) const { if (IsStringObject(pObject)) { LPCWSTR lpszValue = *((CXTPMarkupString*)pObject); CXTPMarkupType* pType = GetClassList()->Lookup(lpszValue); if (pType) { pType->AddRef(); return pType; } } return NULL; } CXTPMarkupType::~CXTPMarkupType() { MARKUP_RELEASE(m_pTypeStyle); } CXTPMarkupObject* CXTPMarkupType::CreateObject(CXTPMarkupContext* pContext) const { _ASSERTE(NULL != m_pfnCreateObject); return (*m_pfnCreateObject)(pContext); } CXTPMarkupType* CXTPMarkupType::GetBaseType() const { _ASSERTE(NULL != m_pfnGetBaseType); return (*m_pfnGetBaseType)(); } void CXTPMarkupType::Register() { if (m_bRegister) return; CXTPMarkupType* pType = GetBaseType(); if (NULL != pType) pType->Register(); m_bRegister = TRUE; if (NULL != m_pfnRegisterMarkupClass) (*m_pfnRegisterMarkupClass)(); } void CXTPMarkupType::Unregister() { if (!m_bRegister) return; m_bRegister = FALSE; if (NULL != m_pfnUnregisterMarkupClass) (*m_pfnUnregisterMarkupClass)(); } void AFX_CDECL CXTPMarkupType::RegisterAll() { GetClassList()->RegisterAll(); } void AFX_CDECL CXTPMarkupType::UnregisterAll() { GetClassList()->UnregisterAll(); } void* AFX_CDECL CXTPMarkupType::RegisterTypeEntry(LPCWSTR lpTag, PFNGETBASETYPE pfnGetType) { return GetClassList()->Register(lpTag, pfnGetType); } void AFX_CDECL CXTPMarkupType::ResolveTypeEntry(void* pTypeEntry) { if (NULL == pTypeEntry) return; reinterpret_cast(pTypeEntry)->GetType(); } BOOL CXTPMarkupType::IsDerivedFrom(const CXTPMarkupType* pBaseClass) const { const CXTPMarkupType* pClassThis = this; while (pClassThis != NULL) { if (pClassThis->IsEqualTo(pBaseClass)) return TRUE; pClassThis = pClassThis->GetBaseType(); } return FALSE; } BOOL CXTPMarkupType::IsEqualTo(const CXTPMarkupType* pType) const { if (NULL == pType) return FALSE; return (m_pfnCreateObject == pType->m_pfnCreateObject); } UINT CXTPMarkupType::GetHashKey() const { return HashKey(m_pfnCreateObject); } CXTPMarkupObject* CXTPMarkupType::DynamicDownCast(CXTPMarkupType* pType, CXTPMarkupObject* pObject) { if (pObject != NULL && pObject->IsKindOf(pType)) return pObject; else return NULL; } CXTPMarkupObject* CXTPMarkupType::StaticDownCast(CXTPMarkupType* pType, CXTPMarkupObject* pObject) { pType; _ASSERTE(pObject == NULL || pObject->IsKindOf(pType)); return pObject; } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupProperties CXTPMarkupProperties::CXTPMarkupProperties(CXTPMarkupObject* pOwner) { m_pOwner = pOwner; m_nTableSize = CXTPMarkupDependencyProperty::s_nCount; m_pTable = new CXTPMarkupObject*[XTPToUIntChecked(m_nTableSize)]; ZeroMemory(m_pTable, m_nTableSize * sizeof(CXTPMarkupObject*)); } CXTPMarkupProperties::~CXTPMarkupProperties() { for (int i = 0; i < m_nTableSize; i++) { MARKUP_RELEASE(m_pTable[i]); } delete[] m_pTable; } BOOL CXTPMarkupProperties::IsPropertyValid(CXTPMarkupDependencyProperty* pProperty) const { if (pProperty->m_nIndex == -1) { _ASSERTE(FALSE); return FALSE; } if (pProperty->m_nIndex >= m_nTableSize) { _ASSERTE(FALSE); return FALSE; } return TRUE; } CXTPMarkupObject* CXTPMarkupProperties::Lookup(CXTPMarkupDependencyProperty* pProperty) const { if (!IsPropertyValid(pProperty)) return NULL; return m_pTable[pProperty->m_nIndex]; } void CXTPMarkupProperties::Copy(CXTPMarkupProperties* pOwner) { if (this != pOwner) { _ASSERTE(pOwner->m_nTableSize == m_nTableSize); for (int i = 0; i < pOwner->m_nTableSize; i++) { if (pOwner->m_pTable[i]) { m_pTable[i] = pOwner->m_pTable[i]; m_pTable[i]->AddRef(); } } } } void CXTPMarkupProperties::Set(CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pValue) { Remove(pProperty); if (NULL != pValue) { m_pTable[pProperty->m_nIndex] = pValue; if (NULL != m_pOwner) { pValue->SetLogicalParent(m_pOwner); } } } void CXTPMarkupProperties::Remove(CXTPMarkupDependencyProperty* pProperty) { if (IsPropertyValid(pProperty)) { int nIndex = pProperty->m_nIndex; if (NULL != m_pTable[nIndex]) { if (NULL != m_pOwner) { m_pTable[nIndex]->SetLogicalParent(NULL); } MARKUP_RELEASE(m_pTable[nIndex]); } } } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupObject IMPLEMENT_MARKUPCLASS_CUSTOM_BASE(NULL, CXTPMarkupObject, CXTPCmdTarget, NULL); CXTPMarkupDependencyProperty* CXTPMarkupObject::m_pNameProperty = NULL; CXTPMarkupDependencyProperty* CXTPMarkupObject::m_pKeyProperty = NULL; void CXTPMarkupObject::RegisterMarkupClass() { m_pNameProperty = CXTPMarkupDependencyProperty::Register(L"Name", MARKUP_TYPE(CXTPMarkupString), MARKUP_TYPE(CXTPMarkupObject)); m_pKeyProperty = CXTPMarkupDependencyProperty::Register(L"Key", MARKUP_TYPE(CXTPMarkupObject), MARKUP_TYPE(CXTPMarkupObject)); } CXTPMarkupObject::CXTPMarkupObject(int /*nReserved = 0*/) : m_pLogicalParent(NULL) , m_pProperties(NULL) , m_pAssociatedProperty(NULL) , m_posExtension(NULL) , m_pMarkupContext(NULL) , m_pMarkupElement(NULL) , m_lpszMarkupTag(NULL) , m_bBeingLoaded(FALSE) , m_pDispColl(NULL) { EnableAutomation(); #ifdef _XTP_ACTIVEX EnableTypeLib(); #endif } CXTPMarkupObject::~CXTPMarkupObject() { if (NULL != m_pMarkupElement) m_pMarkupElement->Release(); if (NULL != m_lpszMarkupTag) free(m_lpszMarkupTag); while (!m_Extensions.IsEmpty()) { CXTPMarkupExtension* pExtension = m_Extensions.RemoveTail(); MARKUP_RELEASE(pExtension); } SAFE_DELETE(m_pProperties); if (NULL != m_pDispColl) delete m_pDispColl; } DWORD CXTPMarkupObject::AddRef() { return InternalAddRef(); } void CXTPMarkupObject::OnFinalRelease() { if (NULL != m_pMarkupContext) { m_pMarkupContext->FinalizeMarkupObject(this); m_pMarkupContext = NULL; } delete this; } DWORD CXTPMarkupObject::Release() { return InternalRelease(); } CXTPMarkupObject* CXTPMarkupObject::ConvertFrom(CXTPMarkupBuilder* /*pBuilder*/, CXTPMarkupObject* /*pObject*/) const { return NULL; } XTPXML::IXMLDOMElement* CXTPMarkupObject::GetSourceMarkupElement() const { return m_pMarkupElement; } void CXTPMarkupObject::SetSourceMarkupElement(XTPXML::IXMLDOMElement* pElement) { _ASSERTE(NULL != pElement); _ASSERTE(NULL == m_pMarkupElement); m_pMarkupElement = pElement; m_pMarkupElement->AddRef(); } LPCWSTR CXTPMarkupObject::GetKey() const { CXTPMarkupObject* pValue = GetValue(m_pKeyProperty); if (NULL == pValue) return NULL; CXTPMarkupString* pString = MARKUP_DYNAMICCAST(CXTPMarkupString, pValue); if (NULL == pString) return NULL; return *pString; } void CXTPMarkupObject::SetKey(LPCWSTR lpszKey) { SetValue(m_pKeyProperty, new CXTPMarkupString(lpszKey)); } LPCWSTR CXTPMarkupObject::GetName() const { CXTPMarkupObject* pValue = GetValue(m_pNameProperty); if (NULL == pValue) return NULL; CXTPMarkupString* pString = MARKUP_DYNAMICCAST(CXTPMarkupString, pValue); if (NULL == pString) return NULL; return *pString; } void CXTPMarkupObject::SetName(LPCWSTR lpszName) { SetValue(m_pNameProperty, new CXTPMarkupString(lpszName)); } void CXTPMarkupObject::SetValue(CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pValue) { ASSERT_VALID(pProperty); if (NULL == pProperty) return; if (NULL != pValue) { BOOL bPropertyTypeMismatch = !pValue->GetType()->IsDerivedFrom(pProperty->GetPropetyType()); _ASSERTE(!bPropertyTypeMismatch); if (bPropertyTypeMismatch) { MARKUP_RELEASE(pValue); return; } } if (NULL == m_pProperties) m_pProperties = new CXTPMarkupProperties(this); CXTPMarkupObject* pOldValue = GetValue(pProperty); if (NULL != pValue && ::IsEqual(pValue, pOldValue)) { MARKUP_RELEASE(pValue); return; } m_pProperties->Set(pProperty, pValue); OnSetValue(pProperty, pOldValue, pValue); } void CXTPMarkupObject::OnSetValue(CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pOldValue, CXTPMarkupObject* pValue) { if (NULL != pValue) pValue->OnSetAsProperty(pProperty, this); CXTPMarkupObject* pNewValue = GetValue(pProperty); OnPropertyChanged(pProperty, pOldValue, pNewValue); if (pProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagInherited) RecursePropertyChanged(pProperty, pOldValue, pNewValue); } void CXTPMarkupObject::RecursePropertyChanged(CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pOldValue, CXTPMarkupObject* pNewValue) { int nCount = GetLogicalChildrenCount(); for (int i = 0; i < nCount; i++) { CXTPMarkupObject* pObject = GetLogicalChild(i); if (!pObject) continue; if (pObject->IsKindOf(pProperty->GetOwnerType())) { pObject->OnPropertyChanged(pProperty, pOldValue, pNewValue); } pObject->RecursePropertyChanged(pProperty, pOldValue, pNewValue); } } void CXTPMarkupObject::OnPropertyChanged(CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pOldValue, CXTPMarkupObject* pNewValue) { if (pProperty->GetMetadata() && pProperty->GetMetadata()->m_pPropertyChanged != NULL) { CXTPMarkupPropertyChangedEventArgs e(pProperty, pOldValue, pNewValue); (*pProperty->GetMetadata()->m_pPropertyChanged)(this, &e); } } void CXTPMarkupObject::OnSetAsProperty(CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pTargetObject) { UNREFERENCED_PARAMETER(pProperty); UNREFERENCED_PARAMETER(pTargetObject); } void CXTPMarkupObject::OnLoaded(CXTPMarkupBuilder* pBuilder) { UNREFERENCED_PARAMETER(pBuilder); } CXTPMarkupObject* CXTPMarkupObject::GetValueSource(CXTPMarkupDependencyProperty* pProperty) const { CXTPMarkupObject* pValue = GetValueCore(pProperty); if (pValue) { return (CXTPMarkupObject*)this; } if (pProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagInherited) { CXTPMarkupObject* pLogicalParent = GetLogicalParent(); while (pLogicalParent) { pValue = pLogicalParent->GetValueCore(pProperty); if (pValue) return pLogicalParent; pLogicalParent = pLogicalParent->GetLogicalParent(); } } return NULL; } CXTPMarkupObject* CXTPMarkupObject::GetValueCore(CXTPMarkupDependencyProperty* pProperty) const { CXTPMarkupObject* pValue = m_pProperties ? m_pProperties->Lookup(pProperty) : NULL; return pValue; } CXTPMarkupObject* CXTPMarkupObject::GetValue(CXTPMarkupDependencyProperty* pProperty) const { CXTPMarkupObject* pValue = GetValueCore(pProperty); if (pValue) return pValue; if (pProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagInherited) { CXTPMarkupObject* pLogicalParent = GetLogicalParent(); while (pLogicalParent) { pValue = pLogicalParent->GetValueCore(pProperty); if (pValue) return pValue; pLogicalParent = pLogicalParent->GetLogicalParent(); } } if (pProperty->GetMetadata() && pProperty->GetMetadata()->m_pDefaultValue) return pProperty->GetMetadata()->m_pDefaultValue; return NULL; } void CXTPMarkupObject::SetLogicalParent(CXTPMarkupObject* pObject) { m_pLogicalParent = pObject; } CXTPMarkupObject* CXTPMarkupObject::GetLogicalParent() const { return m_pLogicalParent; } void CXTPMarkupObject::SetContentObject(CXTPMarkupBuilder* pBuilder, CXTPMarkupObject* pContent) { _ASSERTE(NULL != pContent); if (IsStringObject(pContent)) { pBuilder->ThrowBuilderException( CXTPMarkupBuilder::FormatString(_T("Cannot convert the string '%ls' into a '%ls' ") _T("object"), (LPCTSTR)(LPCWSTR) * ((CXTPMarkupString*)pContent), (LPCTSTR)GetType()->m_lpszClassName)); } else { pBuilder->ThrowBuilderException( CXTPMarkupBuilder::FormatString(_T("Cannot add content to an object of type '%ls'"), (LPCTSTR)GetType()->m_lpszClassName)); } } BOOL CXTPMarkupObject::HasContentObject() const { return FALSE; } BOOL CXTPMarkupObject::AllowWhiteSpaceContent() const { return FALSE; } void CXTPMarkupObject::SetPropertyObject(CXTPMarkupBuilder* pBuilder, CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pValue) { _ASSERTE(NULL != pValue); if (pValue != NULL && !pValue->IsKindOf(pProperty->GetPropetyType())) { CXTPMarkupObject* pNewValue = pBuilder->ConvertValue(pProperty, pValue); SetValue(pProperty, pNewValue); } else { SetValue(pProperty, pValue); MARKUP_ADDREF(pValue); } } void CXTPMarkupObject::SetTagName(LPCWSTR lpszTagName) { _ASSERTE(NULL != lpszTagName); if (NULL != m_lpszMarkupTag) { free(m_lpszMarkupTag); m_lpszMarkupTag = NULL; } if (NULL != lpszTagName) { m_lpszMarkupTag = _wcsdup(lpszTagName); } } LPCWSTR CXTPMarkupObject::GetTagName() const { return m_lpszMarkupTag; } CXTPMarkupObject* CXTPMarkupObject::FindKey(LPCWSTR lpszKey) { CXTPMarkupString* pKey = MARKUP_DYNAMICCAST(CXTPMarkupString, GetValue(m_pKeyProperty)); if ((NULL != pKey) && (0 == ::wcscmp(*pKey, lpszKey))) return this; CXTPMarkupObject* pObject = NULL; const int nCount = GetLogicalChildrenCount(); for (int i = 0; (i < nCount) && (NULL == pObject); i++) pObject = GetLogicalChild(i)->FindKey(lpszKey); return pObject; } CXTPMarkupObject* CXTPMarkupObject::FindName(LPCWSTR lpszName) { CXTPMarkupString* pName = MARKUP_DYNAMICCAST(CXTPMarkupString, GetValue(m_pNameProperty)); if (pName && (wcscmp(*pName, lpszName) == 0)) return this; int nCount = GetLogicalChildrenCount(); for (int i = 0; i < nCount; i++) { CXTPMarkupObject* pResult = GetLogicalChild(i)->FindName(lpszName); if (pResult) return pResult; } return NULL; } int CXTPMarkupObject::GetLogicalChildrenCount() const { return 0; } CXTPMarkupObject* CXTPMarkupObject::GetLogicalChild(int /*nIndex*/) const { _ASSERTE(FALSE); return NULL; } void CXTPMarkupObject::AddExtension(CXTPMarkupExtension* pExtension) { _ASSERTE(NULL != pExtension); m_Extensions.AddTail(pExtension); MARKUP_ADDREF(pExtension); } CXTPMarkupExtension* CXTPMarkupObject::GetNextExtension(const CXTPMarkupType* pClass /*= NULL*/) { CXTPMarkupExtension* pExtension = NULL; if (NULL == m_posExtension) { ResetExtensionEnumerator(); } while (NULL != m_posExtension) { CXTPMarkupExtension* pExt = m_Extensions.GetNext(m_posExtension); if (NULL != pClass) { if (!pExt->IsKindOf(pClass)) { continue; } } pExtension = pExt; break; } return pExtension; } const CXTPMarkupExtension* CXTPMarkupObject::GetNextExtension(const CXTPMarkupType* pClass /*= NULL*/) const { return const_cast(this)->GetNextExtension(pClass); } void CXTPMarkupObject::ResetExtensionEnumerator() { m_posExtension = m_Extensions.GetHeadPosition(); } BOOL CXTPMarkupObject::IsKindOf(const CXTPMarkupType* pClass) const { return GetType()->IsDerivedFrom(pClass); } #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_DISPATCH_MAP(CXTPMarkupObject, CXTPCmdTarget) END_DISPATCH_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" BEGIN_INTERFACE_MAP(CXTPMarkupObject, CXTPCmdTarget) #ifdef _XTP_ACTIVEX INTERFACE_PART(CXTPMarkupObject, XTPDIID_MarkupObject, Dispatch) #endif INTERFACE_PART(CXTPMarkupObject, IID_IDispatchEx, DispatchEx) END_INTERFACE_MAP() #ifdef _XTP_ACTIVEX IMPLEMENT_OLETYPELIB_EX(CXTPMarkupObject, XTPDIID_MarkupObject) #endif CXTPMarkupObject* CXTPMarkupObject::FromDispatch(LPDISPATCH lpElementDisp, BOOL bAddRef) { if (NULL == lpElementDisp) return NULL; CXTPMarkupObject* pObject = XTP_DYNAMIC_DOWNCAST_REMOTE_(CXTPMarkupObject, CXTPMarkupObject::FromIDispatchSafe( lpElementDisp)); if (NULL == pObject) AfxThrowOleException(E_INVALIDARG); if (bAddRef) pObject->InternalAddRef(); return pObject; } CXTPMarkupObject* CXTPMarkupObject::FromDispatchAs(CXTPMarkupType* pType, LPDISPATCH pDisp, BOOL bAddRef /*= TRUE*/) { _ASSERTE(NULL != pType); CXTPMarkupObject* pObject = FromDispatch(pDisp, bAddRef); if (NULL == pObject) return NULL; return CXTPMarkupType::DynamicDownCast(pType, pObject); } XTP_IMPLEMENT_IUNKNOWN(CXTPMarkupObject, DispatchEx); XTP_IMPLEMENT_IDISPATCH(CXTPMarkupObject, DispatchEx); class CXTPMarkupObjectAttachedPropertyElementSO : public CXTPCmdTarget { DECLARE_DYNAMIC(CXTPMarkupObjectAttachedPropertyElementSO); public: explicit CXTPMarkupObjectAttachedPropertyElementSO(CXTPMarkupObject* pObj, LPCWSTR lpName, CXTPMarkupType* pType) : m_pObj(pObj) , m_lpName(_wcsdup(lpName)) , m_pType(pType) { ASSERT_VALID(m_pObj); ASSERT_VALID(m_pType); MARKUP_ADDREF(pObj); MARKUP_ADDREF(pType); EnableAutomation(); } ~CXTPMarkupObjectAttachedPropertyElementSO() { MARKUP_RELEASE(m_pType); MARKUP_RELEASE(m_pObj); free(m_lpName); } private: void CallOnSetValue(CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pOldValue, CXTPMarkupObject* pValue) { m_pObj->OnSetValue(pProperty, pOldValue, pValue); } DECLARE_INTERFACE_MAP(); #pragma warning(push) // C4616: #pragma warning : warning number '...' out of range, must be between '4001' and '4999' // C4619: #pragma warning : there is no warning number 'number' // C5204: '...': class has virtual functions, but its trivial destructor is not virtual; instances // of objects derived from this class may not be destructed correctly #pragma warning(disable : 4616 4619 5204) BEGIN_INTERFACE_PART(DispatchEx, IDispatchEx) XTP_DECLARE_IDISPATCH() // IDispatchEx virtual HRESULT STDMETHODCALLTYPE GetDispID( /* [in] */ BSTR bstrName, /* [in] */ DWORD grfdex, /* [out] */ DISPID* pid) { XTP_UNUSED_PARAMETER(grfdex); METHOD_PROLOGUE(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); if (NULL == bstrName || NULL == pid) return E_POINTER; CXTPMarkupDependencyProperty* pProp = CXTPMarkupDependencyProperty::FindProperty(pThis->m_pType, bstrName); if (NULL == pProp) return DISP_E_MEMBERNOTFOUND; *pid = pThis->m_dispColl.OnGetDispID(bstrName, pProp); if (DISPID_UNKNOWN == *pid) return DISP_E_MEMBERNOTFOUND; return S_OK; } virtual /* [local] */ HRESULT STDMETHODCALLTYPE InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS* pdp, VARIANT* pvarRes, EXCEPINFO* pei, IServiceProvider* pspCaller) { XTP_UNUSED_PARAMETER(pspCaller); XTP_UNUSED_PARAMETER(pei); XTP_UNUSED_PARAMETER(lcid); METHOD_PROLOGUE(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); LPCWSTR lpName = NULL; CXTPMarkupDependencyProperty* pProp = NULL; if (!pThis->m_dispColl.Lookup(id, &lpName, (LPVOID*)&pProp)) return DISP_E_MEMBERNOTFOUND; CXTPMarkupObject* pValue = pThis->m_pObj->GetValue(pProp); if (NULL == pValue) return DISP_E_MEMBERNOTFOUND; if (DISPATCH_PROPERTYGET == wFlags) { if (NULL != pdp && (0 != pdp->cArgs || 0 != pdp->cNamedArgs)) return DISP_E_BADPARAMCOUNT; if (NULL == pvarRes) return DISP_E_PARAMNOTOPTIONAL; ::VariantClear(pvarRes); DISPPARAMS dp = { 0 }; return pValue->GetIDispatch(FALSE)->Invoke(DISPID_VALUE, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dp, pvarRes, pei, NULL); } if (DISPATCH_PROPERTYPUT == wFlags) { HRESULT hr = pValue->GetIDispatch(FALSE)->Invoke(DISPID_VALUE, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, pdp, pvarRes, pei, NULL); if (SUCCEEDED(hr)) pThis->CallOnSetValue(pProp, pValue, pValue); return hr; } return DISP_E_MEMBERNOTFOUND; } virtual HRESULT STDMETHODCALLTYPE DeleteMemberByName( /* [in] */ BSTR bstrName, /* [in] */ DWORD grfdex) { XTP_UNUSED_PARAMETER(bstrName); XTP_UNUSED_PARAMETER(grfdex); METHOD_PROLOGUE(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE DeleteMemberByDispID( /* [in] */ DISPID id) { XTP_UNUSED_PARAMETER(id); METHOD_PROLOGUE(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE GetMemberProperties( /* [in] */ DISPID id, /* [in] */ DWORD grfdexFetch, /* [out] */ DWORD* pgrfdex) { XTP_UNUSED_PARAMETER(id); XTP_UNUSED_PARAMETER(grfdexFetch); XTP_UNUSED_PARAMETER(pgrfdex); METHOD_PROLOGUE(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE GetMemberName( /* [in] */ DISPID id, /* [out] */ BSTR* pbstrName) { XTP_UNUSED_PARAMETER(id); XTP_UNUSED_PARAMETER(pbstrName); METHOD_PROLOGUE(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE GetNextDispID( /* [in] */ DWORD grfdex, /* [in] */ DISPID id, /* [out] */ DISPID* pid) { XTP_UNUSED_PARAMETER(grfdex); XTP_UNUSED_PARAMETER(id); XTP_UNUSED_PARAMETER(pid); METHOD_PROLOGUE(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE GetNameSpaceParent( /* [out] */ IUnknown** ppunk) { XTP_UNUSED_PARAMETER(ppunk); METHOD_PROLOGUE(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); return E_NOTIMPL; } END_INTERFACE_PART(DispatchEx) #pragma warning(pop) private: CXTPMarkupObject* m_pObj; LPWSTR m_lpName; CXTPMarkupType* m_pType; CXTPMarkupObjectAttachedPropertyDispCollection m_dispColl; }; IMPLEMENT_DYNAMIC(CXTPMarkupObjectAttachedPropertyElementSO, CXTPCmdTarget); BEGIN_INTERFACE_MAP(CXTPMarkupObjectAttachedPropertyElementSO, CXTPCmdTarget) INTERFACE_PART(CXTPMarkupObjectAttachedPropertyElementSO, IID_IDispatchEx, DispatchEx) END_INTERFACE_MAP() XTP_IMPLEMENT_IUNKNOWN(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); XTP_IMPLEMENT_IDISPATCH(CXTPMarkupObjectAttachedPropertyElementSO, DispatchEx); // IDispatchEx HRESULT STDMETHODCALLTYPE CXTPMarkupObject::XDispatchEx::GetDispID( /* [in] */ BSTR bstrName, /* [in] */ DWORD grfdex, /* [out] */ DISPID* pid) { XTP_UNUSED_PARAMETER(bstrName); XTP_UNUSED_PARAMETER(grfdex); METHOD_PROLOGUE(CXTPMarkupObject, DispatchEx); if (NULL == pid) return E_POINTER; LPOLESTR name[] = { bstrName }; if (S_OK == pThis->GetIDispatch(FALSE)->GetIDsOfNames(IID_NULL, name, 1, LOCALE_SYSTEM_DEFAULT, pid)) return S_OK; CXTPMarkupType* pType = CXTPMarkupType::LookupTag(bstrName); if (NULL == pType) return DISP_E_MEMBERNOTFOUND; if (NULL == pThis->m_pDispColl) pThis->m_pDispColl = new CXTPMarkupObjectAttachedPropertyDispCollection(); *pid = pThis->m_pDispColl->OnGetDispID(bstrName, pType); if (DISPID_UNKNOWN == *pid) return E_FAIL; return S_OK; } HRESULT STDMETHODCALLTYPE CXTPMarkupObject::XDispatchEx::InvokeEx(DISPID id, LCID lcid, WORD wFlags, DISPPARAMS* pdp, VARIANT* pvarRes, EXCEPINFO* pei, IServiceProvider* pspCaller) { XTP_UNUSED_PARAMETER(pspCaller); METHOD_PROLOGUE(CXTPMarkupObject, DispatchEx); HRESULT hr = pThis->GetIDispatch(FALSE)->Invoke(id, IID_NULL, lcid, wFlags, pdp, pvarRes, pei, NULL); if (SUCCEEDED(hr)) return hr; if (DISPATCH_PROPERTYGET != wFlags) return DISP_E_MEMBERNOTFOUND; if (NULL != pdp && (0 != pdp->cArgs || 0 != pdp->cNamedArgs)) return DISP_E_BADPARAMCOUNT; if (NULL == pvarRes) return DISP_E_PARAMNOTFOUND; if (NULL == pThis->m_pDispColl) return DISP_E_MEMBERNOTFOUND; LPCWSTR lpName = NULL; CXTPMarkupType* pType = NULL; if (!pThis->m_pDispColl->Lookup(id, &lpName, (LPVOID*)&pType)) return DISP_E_MEMBERNOTFOUND; CXTPMarkupObjectAttachedPropertyElementSO* pSO = new CXTPMarkupObjectAttachedPropertyElementSO(pThis, lpName, pType); pvarRes->vt = VT_DISPATCH; pvarRes->pdispVal = pSO->GetIDispatch(TRUE); pSO->InternalRelease(); return S_OK; } HRESULT STDMETHODCALLTYPE CXTPMarkupObject::XDispatchEx::DeleteMemberByName( /* [in] */ BSTR bstrName, /* [in] */ DWORD grfdex) { XTP_UNUSED_PARAMETER(bstrName); XTP_UNUSED_PARAMETER(grfdex); METHOD_PROLOGUE(CXTPMarkupObject, DispatchEx); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CXTPMarkupObject::XDispatchEx::DeleteMemberByDispID( /* [in] */ DISPID id) { XTP_UNUSED_PARAMETER(id); METHOD_PROLOGUE(CXTPMarkupObject, DispatchEx); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CXTPMarkupObject::XDispatchEx::GetMemberProperties( /* [in] */ DISPID id, /* [in] */ DWORD grfdexFetch, /* [out] */ DWORD* pgrfdex) { XTP_UNUSED_PARAMETER(id); XTP_UNUSED_PARAMETER(grfdexFetch); XTP_UNUSED_PARAMETER(pgrfdex); METHOD_PROLOGUE(CXTPMarkupObject, DispatchEx); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CXTPMarkupObject::XDispatchEx::GetMemberName( /* [in] */ DISPID id, /* [out] */ BSTR* pbstrName) { XTP_UNUSED_PARAMETER(id); XTP_UNUSED_PARAMETER(pbstrName); METHOD_PROLOGUE(CXTPMarkupObject, DispatchEx); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CXTPMarkupObject::XDispatchEx::GetNextDispID( /* [in] */ DWORD grfdex, /* [in] */ DISPID id, /* [out] */ DISPID* pid) { XTP_UNUSED_PARAMETER(grfdex); XTP_UNUSED_PARAMETER(id); XTP_UNUSED_PARAMETER(pid); METHOD_PROLOGUE(CXTPMarkupObject, DispatchEx); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CXTPMarkupObject::XDispatchEx::GetNameSpaceParent( /* [out] */ IUnknown** ppunk) { XTP_UNUSED_PARAMETER(ppunk); METHOD_PROLOGUE(CXTPMarkupObject, DispatchEx); return E_NOTIMPL; } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupAutoPtr CXTPMarkupAutoPtr::CXTPMarkupAutoPtr(CXTPMarkupObject* pObject /*= NULL*/) { m_pObject = pObject; } CXTPMarkupAutoPtr::~CXTPMarkupAutoPtr() { MARKUP_RELEASE(m_pObject); } void CXTPMarkupAutoPtr::Assign(CXTPMarkupObject* pObject) { MARKUP_RELEASE(m_pObject); m_pObject = pObject; } CXTPMarkupObject* CXTPMarkupAutoPtr::AddRef() { _ASSERTE(NULL != m_pObject); m_pObject->AddRef(); return m_pObject; } CXTPMarkupObject* CXTPMarkupAutoPtr::operator->() { _ASSERTE(NULL != m_pObject); return m_pObject; } const CXTPMarkupObject* CXTPMarkupAutoPtr::operator->() const { _ASSERTE(NULL != m_pObject); return m_pObject; } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupInt IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupInt, CXTPMarkupObject); #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_DISPATCH_MAP(CXTPMarkupInt, CXTPMarkupObject) DISP_PROPERTY_ID(CXTPMarkupInt, "__value__", DISPID_VALUE, m_nValue, VT_I4) END_DISPATCH_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" void CXTPMarkupInt::RegisterMarkupClass() { } CXTPMarkupInt::CXTPMarkupInt(int nValue) : CXTPMarkupObject(flagNoCom) { m_nValue = nValue; } CXTPMarkupObject* CXTPMarkupInt::ConvertFrom(CXTPMarkupBuilder* pBuilder, CXTPMarkupObject* pObject) const { _ASSERTE(NULL != pBuilder); _ASSERTE(NULL != pObject); CXTPMarkupInt* pValue = NULL; if (IsStringObject(pObject)) { int nValue = _wtoi(*((CXTPMarkupString*)pObject)); if (NULL != m_pAssociatedProperty) { if (0 != (m_pAssociatedProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagHorzDpiSensible)) { nValue = pBuilder->GetMarkupContext()->ScaleX(nValue); } else if (0 != (m_pAssociatedProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagVertDpiSensible)) { nValue = pBuilder->GetMarkupContext()->ScaleY(nValue); } } pValue = new CXTPMarkupInt(nValue); } return pValue; } BOOL CXTPMarkupInt::IsEqual(const CXTPMarkupObject* pObject) const { if (!pObject) return FALSE; if (pObject->GetType() != MARKUP_TYPE(CXTPMarkupInt)) return FALSE; return m_nValue == ((CXTPMarkupInt*)pObject)->m_nValue; } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupDouble IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupDouble, CXTPMarkupObject); void CXTPMarkupDouble::RegisterMarkupClass() { } CXTPMarkupDouble::CXTPMarkupDouble(double dValue) : CXTPMarkupObject(flagNoCom) { m_dValue = dValue; } CXTPMarkupObject* CXTPMarkupDouble::ConvertFrom(CXTPMarkupBuilder* pBuilder, CXTPMarkupObject* pObject) const { _ASSERTE(NULL != pBuilder); _ASSERTE(NULL != pObject); CXTPMarkupDouble* pValue = NULL; if (IsStringObject(pObject)) { LPCWSTR lpszValue = *(CXTPMarkupString*)pObject; double nValue = 0; if (CXTPMarkupBuilder::ConvertDouble(lpszValue, nValue)) { if (NULL != m_pAssociatedProperty) { if (0 != (m_pAssociatedProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagHorzDpiSensible)) { nValue = pBuilder->GetMarkupContext()->ScaleX(nValue); } else if (0 != (m_pAssociatedProperty->GetFlags() & CXTPMarkupPropertyMetadata::flagVertDpiSensible)) { nValue = pBuilder->GetMarkupContext()->ScaleY(nValue); } } pValue = new CXTPMarkupDouble(nValue); } } return pValue; } BOOL CXTPMarkupDouble::IsEqual(const CXTPMarkupObject* pObject) const { if (!pObject) return FALSE; if (pObject->GetType() != MARKUP_TYPE(CXTPMarkupDouble)) return FALSE; return m_dValue == ((CXTPMarkupDouble*)pObject)->m_dValue; } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupEnum IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupEnum, CXTPMarkupObject); void CXTPMarkupEnum::RegisterMarkupClass() { } CXTPMarkupEnum::CXTPMarkupEnum(int nValue) : CXTPMarkupObject(flagNoCom) { m_nValue = nValue; } CXTPMarkupObject* CXTPMarkupEnum::ConvertFrom(CXTPMarkupBuilder* /*pBuilder*/, CXTPMarkupObject* /*pObject*/) const { return NULL; } BOOL CXTPMarkupEnum::IsEqual(const CXTPMarkupObject* pObject) const { if (!pObject) return FALSE; if (pObject->GetType() != MARKUP_TYPE(CXTPMarkupEnum)) return FALSE; return m_nValue == ((CXTPMarkupEnum*)pObject)->m_nValue; } CXTPMarkupEnum* CXTPMarkupEnum::CreateValue(int nValue) { return new CXTPMarkupEnum(nValue); } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupBool IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupBool, CXTPMarkupObject); void CXTPMarkupBool::RegisterMarkupClass() { } CXTPMarkupBool::CXTPMarkupBool(BOOL bValue) : CXTPMarkupObject(flagNoCom) { m_bValue = bValue; } CXTPMarkupBool* CXTPMarkupBool::CreateTrueValue() { return CreateValue(TRUE); } CXTPMarkupBool* CXTPMarkupBool::CreateValue(BOOL bValue) { return new CXTPMarkupBool(bValue); } CXTPMarkupBool* CXTPMarkupBool::CreateFalseValue() { return CreateValue(FALSE); } CXTPMarkupObject* CXTPMarkupBool::ConvertFrom(CXTPMarkupBuilder* pBuilder, CXTPMarkupObject* pObject) const { return CXTPMarkupBuilder::ConvertBool(pBuilder, pObject); } UINT CXTPMarkupBool::GetHashKey() const { return XTPToUInt(m_bValue); } BOOL CXTPMarkupBool::IsEqual(const CXTPMarkupObject* pObject) const { if (!pObject) return FALSE; if (pObject->GetType() != MARKUP_TYPE(CXTPMarkupBool)) return FALSE; if (m_bValue != ((CXTPMarkupBool*)pObject)->m_bValue) return FALSE; return TRUE; } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupColor IMPLEMENT_MARKUPCLASS(L"Color", CXTPMarkupColor, CXTPMarkupObject); void CXTPMarkupColor::RegisterMarkupClass() { } CXTPMarkupColor::CXTPMarkupColor(COLORREF nValue) : CXTPMarkupObject(flagNoCom) { m_nValue = nValue | 0xFF000000; } CXTPMarkupColor::CXTPMarkupColor(BYTE bAlpha, COLORREF nValue) : CXTPMarkupObject(flagNoCom) { m_nValue = (nValue & 0xFFFFFF) | (COLORREF(bAlpha) << 24); } BOOL CXTPMarkupColor::ConvertFromString(LPCWSTR lpszValue, COLORREF& clr) { size_t nLength = wcslen(lpszValue); if (lpszValue[0] == '#' && nLength == 7) { UINT clrRed = 0, clrGreen = 0, clrBlue = 0; if (WSCANF_S(lpszValue, L"#%2x%2x%2x", &clrRed, &clrGreen, &clrBlue) != 3) return FALSE; clr = RGB(clrRed, clrGreen, clrBlue) | 0xFF000000; return TRUE; } if (lpszValue[0] == '#' && nLength == 9) { UINT clrRed = 0, clrGreen = 0, clrBlue = 0, clrAlpha = 0; if (WSCANF_S(lpszValue, L"#%2x%2x%2x%2x", &clrAlpha, &clrRed, &clrGreen, &clrBlue) != 4) return FALSE; clr = RGB(clrRed, clrGreen, clrBlue) | (clrAlpha << 24); return TRUE; } if (lpszValue[0] != '#') { if (CXTPMarkupBuilder::ColorStringToKnownColor(lpszValue, clr)) { return TRUE; } } return FALSE; } CXTPMarkupObject* CXTPMarkupColor::ConvertFrom(CXTPMarkupBuilder* /*pBuilder*/, CXTPMarkupObject* pObject) const { if (IsStringObject(pObject)) { COLORREF clr; if (ConvertFromString(*((CXTPMarkupString*)pObject), clr)) { return new CXTPMarkupColor((BYTE)(clr >> 24), clr & 0xFFFFFF); } } return NULL; } BOOL CXTPMarkupColor::IsEqual(const CXTPMarkupObject* pObject) const { if (!pObject) return FALSE; if (pObject->GetType() != MARKUP_TYPE(CXTPMarkupColor)) return FALSE; return m_nValue == ((CXTPMarkupColor*)pObject)->m_nValue; } void CXTPMarkupColor::SetContentObject(CXTPMarkupBuilder* pBuilder, CXTPMarkupObject* pContent) { if (IsStringObject(pContent)) { COLORREF clr; if (ConvertFromString(*((CXTPMarkupString*)pContent), clr)) { m_nValue = clr; return; } } CXTPMarkupObject::SetContentObject(pBuilder, pContent); } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupColorKey IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupColorKey, CXTPMarkupObject); void CXTPMarkupColorKey::RegisterMarkupClass() { } CXTPMarkupColorKey::CXTPMarkupColorKey(int nIndex /*= 0*/) : CXTPMarkupObject(flagNoCom) , m_nIndex(nIndex) { } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupCollection IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupCollection, CXTPMarkupObject); void CXTPMarkupCollection::RegisterMarkupClass() { } CXTPMarkupCollection::CXTPMarkupCollection() : CXTPMarkupObject(flagNoCom) { m_pElementType = NULL; m_bLogicalParent = TRUE; } CXTPMarkupCollection::~CXTPMarkupCollection() { RemoveAll(); } void CXTPMarkupCollection::RemoveAll() { for (int i = 0; i < m_arrItems.GetSize(); i++) { if (m_bLogicalParent) m_arrItems[i]->SetLogicalParent(NULL); m_arrItems[i]->Release(); } m_arrItems.RemoveAll(); OnChanged(); } void CXTPMarkupCollection::Remove(int nIndex) { if (nIndex < m_arrItems.GetSize()) { CXTPMarkupObject* pItem = m_arrItems[nIndex]; m_arrItems.RemoveAt(nIndex); if (m_bLogicalParent) pItem->SetLogicalParent(NULL); pItem->Release(); OnChanged(); } } void CXTPMarkupCollection::Insert(int nIndex, CXTPMarkupObject* pElement) { _ASSERTE(pElement); _ASSERTE(m_pElementType); _ASSERTE(pElement->IsKindOf(m_pElementType)); if (!pElement || !pElement->IsKindOf(m_pElementType)) return; if (m_bLogicalParent) { _ASSERTE(pElement->GetLogicalParent() == NULL); pElement->SetLogicalParent(this); } if (nIndex < 0 || nIndex > (int)m_arrItems.GetSize()) nIndex = (int)m_arrItems.GetSize(); m_arrItems.InsertAt(nIndex, pElement); OnItemAdded(pElement, nIndex); OnChanged(); } void CXTPMarkupCollection::Add(CXTPMarkupObject* pElement) { Insert((int)m_arrItems.GetSize(), pElement); } int CXTPMarkupCollection::IndexOf(CXTPMarkupObject* pElement) const { for (int i = 0; i < m_arrItems.GetSize(); i++) { if (pElement == m_arrItems[i]) return i; } return -1; } void CXTPMarkupCollection::OnItemAdded(CXTPMarkupObject* /*pItem*/, int /*nIndex*/) { } void CXTPMarkupCollection::OnChanged() { } void CXTPMarkupCollection::SetContentObject(CXTPMarkupBuilder* pBuilder, CXTPMarkupObject* pContent) { _ASSERTE(m_pElementType); if (pContent->IsKindOf(m_pElementType)) { Add(pContent); MARKUP_ADDREF(pContent); } else { pBuilder->ThrowBuilderException(CXTPMarkupBuilder::FormatString( _T("'%ls' object cannot be added to '%ls'. Object cannot be converted to type '%ls'"), (LPCTSTR)pContent->GetType()->m_lpszClassName, (LPCTSTR)GetType()->m_lpszClassName, (LPCTSTR)m_pElementType->m_lpszClassName)); } } BOOL CXTPMarkupCollection::HasContentObject() const { return GetCount() > 0; } int CXTPMarkupCollection::GetLogicalChildrenCount() const { return (int)m_arrItems.GetSize(); } CXTPMarkupObject* CXTPMarkupCollection::GetLogicalChild(int nIndex) const { return m_arrItems[nIndex]; } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupDoubleCollection IMPLEMENT_MARKUPCLASS(L"DoubleCollection", CXTPMarkupDoubleCollection, CXTPMarkupObject) void CXTPMarkupDoubleCollection::RegisterMarkupClass() { } CXTPMarkupDoubleCollection::CXTPMarkupDoubleCollection() : CXTPMarkupObject(flagNoCom) { } CXTPMarkupDoubleCollection::CXTPMarkupDoubleCollection(CDoubleArray& arr) : CXTPMarkupObject(flagNoCom) { m_arr.Copy(arr); } int CXTPMarkupDoubleCollection::GetCount() const { return (int)m_arr.GetSize(); } const float* CXTPMarkupDoubleCollection::GetData() const { return m_arr.GetData(); } float CXTPMarkupDoubleCollection::GetAt(int nIndex) const { return m_arr.GetAt(nIndex); } void CXTPMarkupDoubleCollection::RemoveAll() { m_arr.RemoveAll(); } void CXTPMarkupDoubleCollection::Remove(int nIndex) { m_arr.RemoveAt(nIndex); } void CXTPMarkupDoubleCollection::Add(float fValue) { m_arr.Add(fValue); } BOOL CXTPMarkupDoubleCollection::GetNextValue(LPCWSTR& lpszValue, float& fValue) { if (!XTP_ASSERT_CHECK(NULL != lpszValue)) return FALSE; int nEndPos = 0; double dValue = XTPParseDouble(lpszValue, &nEndPos); if (XTP_ISNAN(dValue)) return FALSE; lpszValue += nEndPos; fValue = static_cast(dValue); return TRUE; } BOOL CXTPMarkupDoubleCollection::ConvertFromString(LPCWSTR lpszValue, CDoubleArray& arr) { if (!lpszValue) return FALSE; while (*lpszValue != 0) { float x; if (!GetNextValue(lpszValue, x)) return FALSE; while (L' ' == *lpszValue) ++lpszValue; if (L',' == *lpszValue) ++lpszValue; while (L' ' == *lpszValue) ++lpszValue; arr.Add(x); } return TRUE; } CXTPMarkupObject* CXTPMarkupDoubleCollection::ConvertFrom(CXTPMarkupBuilder* /*pBuilder*/, CXTPMarkupObject* pObject) const { if (IsStringObject(pObject)) { CDoubleArray arr; if (ConvertFromString(*((CXTPMarkupString*)pObject), arr)) { return new CXTPMarkupDoubleCollection(arr); } } return NULL; } ////////////////////////////////////////////////////////////////////////// // CXTPMarkupDoubleCollection #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_DISPATCH_MAP(CXTPMarkupDoubleCollection, CXTPMarkupObject) DISP_FUNCTION_ID(CXTPMarkupDoubleCollection, "Count", 1, OleGetItemCount, VT_I4, VTS_NONE) DISP_FUNCTION_ID(CXTPMarkupDoubleCollection, "Item", DISPID_VALUE, OleGetItem, VT_R8, VTS_I4) DISP_FUNCTION_ID(CXTPMarkupDoubleCollection, "Add", 2, OleAdd, VT_EMPTY, VTS_R8) DISP_FUNCTION_ID(CXTPMarkupDoubleCollection, "Clear", 4, RemoveAll, VT_EMPTY, VTS_NONE) DISP_FUNCTION_ID(CXTPMarkupDoubleCollection, "RemoveAt", 5, Remove, VT_EMPTY, VTS_I4) END_DISPATCH_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" #ifdef _XTP_ACTIVEX BEGIN_INTERFACE_MAP(CXTPMarkupDoubleCollection, CXTPMarkupObject) INTERFACE_PART(CXTPMarkupDoubleCollection, XTPDIID_MarkupDoubleCollection, Dispatch) END_INTERFACE_MAP() IMPLEMENT_OLETYPELIB_EX(CXTPMarkupDoubleCollection, XTPDIID_MarkupDoubleCollection) #endif long CXTPMarkupDoubleCollection::OleGetItemCount() { return (long)GetCount(); } double CXTPMarkupDoubleCollection::OleGetItem(long nIndex) { return GetAt(nIndex); } void CXTPMarkupDoubleCollection::OleAdd(double dValue) { Add((float)dValue); }