/*********************************************************************** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY DEVELOPER: Zihan Chen(vczh) ***********************************************************************/ #include "GacUIReflection.h" /*********************************************************************** GUIINSTANCEHELPERTYPES.CPP ***********************************************************************/ namespace vl { namespace presentation { namespace helper_types { } } #ifndef VCZH_DEBUG_NO_REFLECTION namespace reflection { namespace description { using namespace presentation::helper_types; /*********************************************************************** Type Declaration ***********************************************************************/ GUIREFLECTIONHELPERTYPES_TYPELIST(IMPL_VL_TYPE_INFO) #define _ , BEGIN_STRUCT_MEMBER(SiteValue) STRUCT_MEMBER(row) STRUCT_MEMBER(column) STRUCT_MEMBER(rowSpan) STRUCT_MEMBER(columnSpan) END_STRUCT_MEMBER(SiteValue) BEGIN_ENUM_ITEM(ListViewViewType) ENUM_ITEM_NAMESPACE(ListViewViewType) ENUM_NAMESPACE_ITEM(BigIcon) ENUM_NAMESPACE_ITEM(SmallIcon) ENUM_NAMESPACE_ITEM(List) ENUM_NAMESPACE_ITEM(Tile) ENUM_NAMESPACE_ITEM(Information) ENUM_NAMESPACE_ITEM(Detail) END_ENUM_ITEM(ListViewViewType) #undef _ } } namespace presentation { using namespace reflection::description; using namespace controls; /*********************************************************************** Type Loader ***********************************************************************/ class GuiHelperTypesLoader : public Object, public ITypeLoader { public: void Load(ITypeManager* manager) { GUIREFLECTIONHELPERTYPES_TYPELIST(ADD_TYPE_INFO) } void Unload(ITypeManager* manager) { } }; /*********************************************************************** GuiHelperTypesLoaderPlugin ***********************************************************************/ class GuiHelperTypesLoaderPlugin : public Object, public IGuiPlugin { public: void Load()override { ITypeManager* manager=GetGlobalTypeManager(); if(manager) { Ptr loader=new GuiHelperTypesLoader; manager->AddTypeLoader(loader); } } void AfterLoad()override { } void Unload()override { } }; GUI_REGISTER_PLUGIN(GuiHelperTypesLoaderPlugin) } #endif } /*********************************************************************** GUIINSTANCELOADER.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace collections; using namespace parsing; using namespace parsing::xml; using namespace parsing::tabling; using namespace controls; using namespace regex; using namespace reflection::description; using namespace stream; using namespace workflow; using namespace workflow::analyzer; /*********************************************************************** GuiInstancePropertyInfo ***********************************************************************/ Ptr GuiInstancePropertyInfo::Unsupported() { return new GuiInstancePropertyInfo; } Ptr GuiInstancePropertyInfo::Assign(description::ITypeDescriptor* typeDescriptor) { Ptr info = new GuiInstancePropertyInfo; info->support = SupportAssign; if (typeDescriptor) info->acceptableTypes.Add(typeDescriptor); return info; } Ptr GuiInstancePropertyInfo::AssignWithParent(description::ITypeDescriptor* typeDescriptor) { Ptr info = Assign(typeDescriptor); info->tryParent = true; return info; } Ptr GuiInstancePropertyInfo::Collection(description::ITypeDescriptor* typeDescriptor) { Ptr info = Assign(typeDescriptor); info->support = SupportCollection; return info; } Ptr GuiInstancePropertyInfo::CollectionWithParent(description::ITypeDescriptor* typeDescriptor) { Ptr info = Collection(typeDescriptor); info->tryParent = true; return info; } Ptr GuiInstancePropertyInfo::Set(description::ITypeDescriptor* typeDescriptor) { Ptr info = new GuiInstancePropertyInfo; info->support = SupportSet; if (typeDescriptor) info->acceptableTypes.Add(typeDescriptor); return info; } Ptr GuiInstancePropertyInfo::Array(description::ITypeDescriptor* typeDescriptor) { Ptr info = new GuiInstancePropertyInfo; info->support = SupportArray; if (typeDescriptor) info->acceptableTypes.Add(typeDescriptor); return info; } /*********************************************************************** IGuiInstanceLoader ***********************************************************************/ void IGuiInstanceLoader::GetPropertyNames(const TypeInfo& typeInfo, collections::List& propertyNames) { } void IGuiInstanceLoader::GetConstructorParameters(const TypeInfo& typeInfo, collections::List& propertyNames) { } void IGuiInstanceLoader::GetPairedProperties(const PropertyInfo& propertyInfo, collections::List& propertyNames) { } Ptr IGuiInstanceLoader::GetPropertyType(const PropertyInfo& propertyInfo) { return nullptr; } bool IGuiInstanceLoader::CanCreate(const TypeInfo& typeInfo) { return false; } Ptr IGuiInstanceLoader::CreateInstance(const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, collections::List& errors) { CHECK_FAIL(L"IGuiInstanceLoader::CreateInstance(const TypeInfo&, GlobalStringKey, ArgumentMap&)#This function is not implemented."); } Ptr IGuiInstanceLoader::AssignParameters(const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, collections::List& errors) { CHECK_FAIL(L"IGuiInstanceLoader::AssignParameters(const TypeInfo&, GlobalStringKey, ArgumentMap&)#This function is not implemented."); } Ptr IGuiInstanceLoader::GetParameter(const PropertyInfo& propertyInfo, GlobalStringKey variableName, collections::List& errors) { CHECK_FAIL(L"IGuiInstanceLoader::GetParameter(const PropertyInfo&, GlobalStringKey)#This function is not implemented."); } /*********************************************************************** GuiInstanceContext::ElementName Parser ***********************************************************************/ class GuiInstanceContextElementNameParser : public Object, public IGuiParser { typedef GuiInstanceContext::ElementName ElementName; public: Regex regexElementName; GuiInstanceContextElementNameParser() :regexElementName(L"(([a-zA-Z_]/w*):)?(([a-zA-Z_]/w*).)?([a-zA-Z_]/w*)(-([a-zA-Z_]/w*))?") { } Ptr TypedParse(const WString& text, collections::List& errors)override { Ptr match = regexElementName.MatchHead(text); if (!match || match->Result().Length() != text.Length()) { errors.Add(L"Failed to parse an element name \"" + text + L"\"."); return 0; } Ptr elementName = new ElementName; if (match->Groups().Keys().Contains(L"namespaceName")) { elementName->namespaceName = match->Groups()[L"namespaceName"][0].Value(); } if (match->Groups().Keys().Contains(L"category")) { elementName->category = match->Groups()[L"category"][0].Value(); } if (match->Groups().Keys().Contains(L"name")) { elementName->name = match->Groups()[L"name"][0].Value(); } if (match->Groups().Keys().Contains(L"binding")) { elementName->binding = match->Groups()[L"binding"][0].Value(); } return elementName; } }; /*********************************************************************** GuiDefaultInstanceLoader ***********************************************************************/ class GuiDefaultInstanceLoader : public Object, public IGuiInstanceLoader { protected: typedef Tuple FieldKey; typedef Tuple, IPropertyInfo*> PropertyType; Dictionary propertyTypes; public: static IMethodInfo* GetDefaultConstructor(ITypeDescriptor* typeDescriptor) { if (auto ctors = typeDescriptor->GetConstructorGroup()) { vint count = ctors->GetMethodCount(); for (vint i = 0; i < count; i++) { IMethodInfo* method = ctors->GetMethod(i); if (method->GetParameterCount() == 0) { return method; } } } return 0; } GlobalStringKey GetTypeName()override { return GlobalStringKey::Empty; } //*********************************************************************************** void ProcessGenericType(ITypeInfo* propType, ITypeInfo*& genericType, ITypeInfo*& elementType, bool& readableList, bool& writableList, bool& collectionType) { genericType = 0; elementType = 0; readableList = false; writableList = false; collectionType = false; if (propType->GetDecorator() == ITypeInfo::SharedPtr && propType->GetElementType()->GetDecorator() == ITypeInfo::Generic) { propType = propType->GetElementType(); genericType = propType->GetElementType(); if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor()) { elementType = propType->GetGenericArgument(0); readableList = true; writableList = true; collectionType = true; } else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor()) { collectionType = true; } else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor()) { elementType = propType->GetGenericArgument(0); readableList = true; collectionType = true; } else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor()) { elementType = propType->GetGenericArgument(0); readableList = true; collectionType = true; } else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor()) { collectionType = true; } else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor()) { collectionType = true; } } } ITypeInfo* GetPropertyReflectionTypeInfo(const PropertyInfo& propertyInfo, GuiInstancePropertyInfo::Support& support) { support = GuiInstancePropertyInfo::NotSupport; IPropertyInfo* prop = propertyInfo.typeInfo.typeDescriptor->GetPropertyByName(propertyInfo.propertyName.ToString(), true); if (prop) { ITypeInfo* propType = prop->GetReturn(); ITypeInfo* genericType = 0; ITypeInfo* elementType = 0; bool readableList = false; bool writableList = false; bool collectionType = false; ProcessGenericType(propType, genericType, elementType, readableList, writableList, collectionType); if (prop->IsWritable()) { if (collectionType) { if (readableList) { support = GuiInstancePropertyInfo::SupportArray; return elementType; } } else if (genericType) { support = GuiInstancePropertyInfo::SupportAssign; return genericType; } else { support = GuiInstancePropertyInfo::SupportAssign; return propType; } } else if (prop->IsReadable()) { if (collectionType) { if (writableList) { support = GuiInstancePropertyInfo::SupportCollection; return elementType; } } else if (!genericType) { if (propType->GetDecorator() == ITypeInfo::SharedPtr || propType->GetDecorator() == ITypeInfo::RawPtr) { support = GuiInstancePropertyInfo::SupportSet; return propType; } } } } return 0; } bool FillPropertyInfo(Ptr propertyInfo, ITypeInfo* propType) { switch (propType->GetDecorator()) { case ITypeInfo::RawPtr: case ITypeInfo::SharedPtr: case ITypeInfo::Nullable: FillPropertyInfo(propertyInfo, propType->GetElementType()); return true; case ITypeInfo::TypeDescriptor: propertyInfo->acceptableTypes.Add(propType->GetTypeDescriptor()); return true; default:; } return false; } void CollectPropertyNames(const TypeInfo& typeInfo, ITypeDescriptor* typeDescriptor, collections::List& propertyNames) { vint propertyCount = typeDescriptor->GetPropertyCount(); for (vint i = 0; i < propertyCount; i++) { GlobalStringKey propertyName = GlobalStringKey::Get(typeDescriptor->GetProperty(i)->GetName()); if (!propertyNames.Contains(propertyName)) { auto info = GetPropertyType(PropertyInfo(typeInfo, propertyName)); if (info && info->support != GuiInstancePropertyInfo::NotSupport) { propertyNames.Add(propertyName); } } } vint parentCount = typeDescriptor->GetBaseTypeDescriptorCount(); for (vint i = 0; i < parentCount; i++) { CollectPropertyNames(typeInfo, typeDescriptor->GetBaseTypeDescriptor(i), propertyNames); } } bool ContainsViewModels(const TypeInfo& typeInfo) { if (auto ctors = typeInfo.typeDescriptor->GetConstructorGroup()) { if (ctors->GetMethodCount() == 1) { IMethodInfo* method = ctors->GetMethod(0); vint count = method->GetParameterCount(); for (vint i = 0; i < count; i++) { auto parameter = method->GetParameter(i); auto prop = typeInfo.typeDescriptor->GetPropertyByName(parameter->GetName(), false); if (!prop || !prop->GetGetter() || prop->GetSetter() || prop->GetValueChangedEvent()) return false; if (parameter->GetType()->GetTypeFriendlyName() != prop->GetReturn()->GetTypeFriendlyName()) return false; } return true; } } return false; } //*********************************************************************************** void GetPropertyNames(const TypeInfo& typeInfo, collections::List& propertyNames)override { CollectPropertyNames(typeInfo, typeInfo.typeDescriptor, propertyNames); } void GetConstructorParameters(const TypeInfo& typeInfo, collections::List& propertyNames)override { if (ContainsViewModels(typeInfo)) { IMethodInfo* method = typeInfo.typeDescriptor->GetConstructorGroup()->GetMethod(0); vint count = method->GetParameterCount(); for (vint i = 0; i < count; i++) { propertyNames.Add(GlobalStringKey::Get(method->GetParameter(i)->GetName())); } } } PropertyType GetPropertyTypeCached(const PropertyInfo& propertyInfo) { FieldKey key(propertyInfo.typeInfo.typeDescriptor, propertyInfo.propertyName); vint index = propertyTypes.Keys().IndexOf(key); if (index == -1) { GuiInstancePropertyInfo::Support support = GuiInstancePropertyInfo::NotSupport; if (ITypeInfo* propType = GetPropertyReflectionTypeInfo(propertyInfo, support)) { Ptr result = new GuiInstancePropertyInfo; result->support = support; if (ContainsViewModels(propertyInfo.typeInfo)) { IMethodInfo* method = propertyInfo.typeInfo.typeDescriptor->GetConstructorGroup()->GetMethod(0); vint count = method->GetParameterCount(); for (vint i = 0; i < count; i++) { if (method->GetParameter(i)->GetName() == propertyInfo.propertyName.ToString()) { result->scope = GuiInstancePropertyInfo::ViewModel; } } } if (FillPropertyInfo(result, propType)) { IPropertyInfo* prop = propertyInfo.typeInfo.typeDescriptor->GetPropertyByName(propertyInfo.propertyName.ToString(), true); PropertyType value(result, prop); propertyTypes.Add(key, value); return value; } } PropertyType value(GuiInstancePropertyInfo::Unsupported(), 0); propertyTypes.Add(key, value); return value; } else { return propertyTypes.Values()[index]; } } Ptr GetPropertyType(const PropertyInfo& propertyInfo)override { return GetPropertyTypeCached(propertyInfo).f0; } //*********************************************************************************** bool CanCreate(const TypeInfo& typeInfo)override { return GetDefaultConstructor(typeInfo.typeDescriptor) != 0; } Ptr CreateInstance(const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, collections::List& errors)override { auto create = MakePtr(); create->type = GetTypeFromTypeInfo(GetDefaultConstructor(typeInfo.typeDescriptor)->GetReturn()); auto refValue = MakePtr(); refValue->name.value = variableName.ToString(); auto assign = MakePtr(); assign->op = WfBinaryOperator::Assign; assign->first = refValue; assign->second = create; auto stat = MakePtr(); stat->expression = assign; return stat; } Ptr AssignParameters(const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, collections::List& errors)override { auto block = MakePtr(); FOREACH_INDEXER(GlobalStringKey, prop, index, arguments.Keys()) { PropertyType propertyType = GetPropertyTypeCached(PropertyInfo(typeInfo, prop)); if (propertyType.f1) { switch (propertyType.f0->support) { case GuiInstancePropertyInfo::SupportCollection: { const auto& values = arguments.GetByIndex(index); if (values.Count() > 0) { { auto refValue = MakePtr(); refValue->name.value = variableName.ToString(); auto refProp = MakePtr(); refProp->parent = refValue; refProp->name.value = prop.ToString(); auto varDesc = MakePtr(); varDesc->name.value = L""; varDesc->expression = refProp; auto stat = MakePtr(); stat->variable = varDesc; block->statements.Add(stat); } for (vint i = 0; i < values.Count(); i++) { auto refCollection = MakePtr(); refCollection->name.value = L""; auto refAdd = MakePtr(); refAdd->parent = refCollection; refAdd->name.value = L"Add"; auto call = MakePtr(); call->function = refAdd; call->arguments.Add(values[i].expression); auto stat = MakePtr(); stat->expression = call; block->statements.Add(stat); } } } break; case GuiInstancePropertyInfo::SupportAssign: case GuiInstancePropertyInfo::SupportArray: { auto refValue = MakePtr(); refValue->name.value = variableName.ToString(); auto refProp = MakePtr(); refProp->parent = refValue; refProp->name.value = prop.ToString(); auto assign = MakePtr(); assign->op = WfBinaryOperator::Assign; assign->first = refProp; assign->second = arguments.GetByIndex(index)[0].expression; auto stat = MakePtr(); stat->expression = assign; block->statements.Add(stat); } break; default:; } } } if (block->statements.Count() > 0) { return block; } return nullptr; } Ptr GetParameter(const PropertyInfo& propertyInfo, GlobalStringKey variableName, collections::List& errors)override { auto refValue = MakePtr(); refValue->name.value = variableName.ToString(); auto refProp = MakePtr(); refProp->parent = refValue; refProp->name.value = propertyInfo.propertyName.ToString(); return refProp; } }; /*********************************************************************** FindInstanceLoadingSource ***********************************************************************/ InstanceLoadingSource FindInstanceLoadingSource( Ptr context, GuiConstructorRepr* ctor ) { vint index=context->namespaces.Keys().IndexOf(ctor->typeNamespace); if(index!=-1) { Ptr namespaceInfo=context->namespaces.Values()[index]; FOREACH(Ptr, ns, namespaceInfo->namespaces) { auto fullName = GlobalStringKey::Get(ns->prefix + ctor->typeName.ToString() + ns->postfix); IGuiInstanceLoader* loader = GetInstanceLoaderManager()->GetLoader(fullName); if(loader) { return InstanceLoadingSource(loader, fullName); } } } return InstanceLoadingSource(); } /*********************************************************************** GuiInstanceLoaderManager ***********************************************************************/ IGuiInstanceLoaderManager* instanceLoaderManager = 0; IGuiInstanceLoaderManager* GetInstanceLoaderManager() { return instanceLoaderManager; } class GuiInstanceLoaderManager : public Object, public IGuiInstanceLoaderManager, public IGuiPlugin { protected: typedef Dictionary> BinderMap; typedef Dictionary> EventBinderMap; struct VirtualTypeInfo { GlobalStringKey typeName; ITypeDescriptor* typeDescriptor = nullptr; GlobalStringKey parentTypeName; // for virtual type only Ptr loader; List parentTypes; // all direct or indirect base types that does not has a type info List parentTypeInfos; // type infos for all registered direct or indirect base types }; typedef Dictionary> VirtualTypeInfoMap; typedef Dictionary> ResourceMap; typedef Pair, Ptr> ResourceItemPair; typedef Dictionary ResourceItemMap; Ptr rootLoader; BinderMap binders; EventBinderMap eventBinders; VirtualTypeInfoMap typeInfos; ResourceMap resources; ResourceItemMap instanceCtors; bool IsTypeExists(GlobalStringKey name) { return GetGlobalTypeManager()->GetTypeDescriptor(name.ToString()) != 0 || typeInfos.Keys().Contains(name); } void FindParentTypeInfos(Ptr typeInfo, ITypeDescriptor* searchType) { if (searchType != typeInfo->typeDescriptor) { vint index = typeInfos.Keys().IndexOf(GlobalStringKey::Get(searchType->GetTypeName())); if (index == -1) { typeInfo->parentTypes.Add(searchType); } else { typeInfo->parentTypeInfos.Add(typeInfos.Values()[index].Obj()); return; } } vint count = searchType->GetBaseTypeDescriptorCount(); for (vint i = 0; i < count; i++) { ITypeDescriptor* baseType = searchType->GetBaseTypeDescriptor(i); FindParentTypeInfos(typeInfo, baseType); } } void FillParentTypeInfos(Ptr typeInfo) { if (typeInfo->parentTypeName != GlobalStringKey::Empty) { typeInfo->typeDescriptor = nullptr; } typeInfo->parentTypes.Clear(); typeInfo->parentTypeInfos.Clear(); ITypeDescriptor* searchType = typeInfo->typeDescriptor; if (!searchType) { vint index = typeInfos.Keys().IndexOf(typeInfo->parentTypeName); if (index == -1) { searchType = GetGlobalTypeManager()->GetTypeDescriptor(typeInfo->parentTypeName.ToString()); typeInfo->typeDescriptor = searchType; typeInfo->parentTypes.Add(searchType); } else { VirtualTypeInfo* parentTypeInfo = typeInfos.Values()[index].Obj(); typeInfo->typeDescriptor = parentTypeInfo->typeDescriptor; typeInfo->parentTypeInfos.Add(parentTypeInfo); return; } } if (searchType) { FindParentTypeInfos(typeInfo, searchType); } } IGuiInstanceLoader* GetLoaderFromType(ITypeDescriptor* typeDescriptor) { vint index = typeInfos.Keys().IndexOf(GlobalStringKey::Get(typeDescriptor->GetTypeName())); if (index == -1) { vint count = typeDescriptor->GetBaseTypeDescriptorCount(); for (vint i = 0; i < count; i++) { ITypeDescriptor* baseType = typeDescriptor->GetBaseTypeDescriptor(i); IGuiInstanceLoader* loader = GetLoaderFromType(baseType); if (loader) return loader; } return 0; } else { return typeInfos.Values()[index]->loader.Obj(); } } void GetClassesInResource(Ptr resource, Ptr folder) { FOREACH(Ptr, item, folder->GetItems()) { if (auto compiled = item->GetContent().Cast()) { if (compiled->type == GuiInstanceCompiledWorkflow::InstanceCtor) { if (!instanceCtors.Keys().Contains(compiled->classFullName)) { instanceCtors.Add(compiled->classFullName, ResourceItemPair(resource, item)); } } } } FOREACH(Ptr, subFolder, folder->GetFolders()) { GetClassesInResource(resource, subFolder); } } public: GuiInstanceLoaderManager() { rootLoader = new GuiDefaultInstanceLoader; } void Load()override { instanceLoaderManager = this; } void AfterLoad()override { IGuiParserManager* manager = GetParserManager(); manager->SetParser(L"INSTANCE-ELEMENT-NAME", new GuiInstanceContextElementNameParser); } void Unload()override { instanceLoaderManager = 0; } bool AddInstanceBinder(Ptr binder)override { if (binders.Keys().Contains(binder->GetBindingName())) return false; binders.Add(binder->GetBindingName(), binder); return true; } IGuiInstanceBinder* GetInstanceBinder(GlobalStringKey bindingName)override { vint index = binders.Keys().IndexOf(bindingName); return index == -1 ? 0 : binders.Values()[index].Obj(); } bool AddInstanceEventBinder(Ptr binder)override { if (eventBinders.Keys().Contains(binder->GetBindingName())) return false; eventBinders.Add(binder->GetBindingName(), binder); return true; } IGuiInstanceEventBinder* GetInstanceEventBinder(GlobalStringKey bindingName)override { vint index = eventBinders.Keys().IndexOf(bindingName); return index == -1 ? 0 : eventBinders.Values()[index].Obj(); } bool CreateVirtualType(GlobalStringKey parentType, Ptr loader)override { if (IsTypeExists(loader->GetTypeName()) || !IsTypeExists(parentType)) return false; Ptr typeInfo = new VirtualTypeInfo; typeInfo->typeName = loader->GetTypeName(); typeInfo->parentTypeName = parentType; typeInfo->loader = loader; typeInfos.Add(loader->GetTypeName(), typeInfo); FillParentTypeInfos(typeInfo); return true; } bool SetLoader(Ptr loader)override { vint index = typeInfos.Keys().IndexOf(loader->GetTypeName()); if (index != -1) return false; ITypeDescriptor* typeDescriptor = GetGlobalTypeManager()->GetTypeDescriptor(loader->GetTypeName().ToString()); if (typeDescriptor == 0) return false; Ptr typeInfo = new VirtualTypeInfo; typeInfo->typeName = loader->GetTypeName(); typeInfo->typeDescriptor = typeDescriptor; typeInfo->loader = loader; typeInfos.Add(typeInfo->typeName, typeInfo); FillParentTypeInfos(typeInfo); FOREACH(Ptr, derived, typeInfos.Values()) { if (derived->parentTypes.Contains(typeInfo->typeDescriptor)) { FillParentTypeInfos(derived); } } return true; } IGuiInstanceLoader* GetLoader(GlobalStringKey typeName)override { vint index = typeInfos.Keys().IndexOf(typeName); if (index != -1) { return typeInfos.Values()[index]->loader.Obj(); } ITypeDescriptor* typeDescriptor = GetGlobalTypeManager()->GetTypeDescriptor(typeName.ToString()); if (typeDescriptor) { IGuiInstanceLoader* loader = GetLoaderFromType(typeDescriptor); return loader ? loader : rootLoader.Obj(); } return 0; } IGuiInstanceLoader* GetParentLoader(IGuiInstanceLoader* loader)override { vint index = typeInfos.Keys().IndexOf(loader->GetTypeName()); if (index != -1) { Ptr typeInfo = typeInfos.Values()[index]; if (typeInfo->parentTypeInfos.Count() > 0) { return typeInfo->parentTypeInfos[0]->loader.Obj(); } return rootLoader.Obj(); } return 0; } description::ITypeDescriptor* GetTypeDescriptorForType(GlobalStringKey typeName)override { vint index = typeInfos.Keys().IndexOf(typeName); return index == -1 ? GetGlobalTypeManager()->GetTypeDescriptor(typeName.ToString()) : typeInfos.Values()[index]->typeDescriptor; } void GetVirtualTypes(collections::List& typeNames)override { for (vint i = 0; i < typeInfos.Count(); i++) { if (typeInfos.Values()[i]->parentTypeName != GlobalStringKey::Empty) { typeNames.Add(typeInfos.Keys()[i]); } } } GlobalStringKey GetParentTypeForVirtualType(GlobalStringKey virtualType)override { vint index = typeInfos.Keys().IndexOf(virtualType); if (index != -1) { auto typeInfo = typeInfos.Values()[index]; return typeInfo->parentTypeName; } return GlobalStringKey::Empty; } bool SetResource(const WString& name, Ptr resource, GuiResourceUsage usage)override { vint index = resources.Keys().IndexOf(name); if (index != -1) return false; resource->Initialize(usage); resources.Add(name, resource); GetClassesInResource(resource, resource); return true; } Ptr GetResource(const WString& name)override { vint index = resources.Keys().IndexOf(name); return index == -1 ? nullptr : resources.Values()[index]; } Ptr RunInstanceConstructor(const WString& classFullName, description::Value instance)override { vint index = instanceCtors.Keys().IndexOf(classFullName); if (index == -1) return nullptr; auto pair = instanceCtors.Values()[index]; auto context = Workflow_RunPrecompiledScript(pair.key, pair.value, instance); auto result = MakePtr(); result->context = context; return result; } }; GUI_REGISTER_PLUGIN(GuiInstanceLoaderManager) } } /*********************************************************************** GUIINSTANCELOADER_PREDEFINEDINSTANCEBINDERS.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace collections; using namespace reflection::description; using namespace workflow; using namespace workflow::analyzer; using namespace workflow::runtime; using namespace controls; /*********************************************************************** GuiResourceInstanceBinder (uri) ***********************************************************************/ class GuiResourceInstanceBinder : public Object, public IGuiInstanceBinder { public: GlobalStringKey GetBindingName()override { return GlobalStringKey::_Uri; } bool ApplicableToConstructorArgument()override { return false; } Ptr GenerateInstallStatement(GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, const WString& code, collections::List& errors)override { WString protocol, path; if (!IsResourceUrl(code, protocol, path)) { errors.Add(L"Precompile: \"" + code + L"\" is not a valid resource uri."); return 0; } else { return Workflow_InstallUriProperty(variableName, propertyInfo, protocol, path); } } }; /*********************************************************************** GuiReferenceInstanceBinder (ref) ***********************************************************************/ class GuiReferenceInstanceBinder : public Object, public IGuiInstanceBinder { public: GlobalStringKey GetBindingName()override { return GlobalStringKey::_Ref; } bool ApplicableToConstructorArgument()override { return false; } Ptr GenerateInstallStatement(GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, const WString& code, collections::List& errors)override { auto expression = MakePtr(); expression->name.value = code; return Workflow_InstallEvalProperty(variableName, propertyInfo, expression); } }; /*********************************************************************** GuiEvalInstanceBinder (eval) ***********************************************************************/ class GuiEvalInstanceBinder : public Object, public IGuiInstanceBinder { public: GlobalStringKey GetBindingName()override { return GlobalStringKey::_Eval; } bool ApplicableToConstructorArgument()override { return true; } Ptr GenerateInstallStatement(GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, const WString& code, collections::List& errors)override { if (auto expression = Workflow_ParseExpression(code, errors)) { return Workflow_InstallEvalProperty(variableName, propertyInfo, expression); } return 0; } }; /*********************************************************************** GuiBindInstanceBinder (bind) ***********************************************************************/ class GuiBindInstanceBinder : public Object, public IGuiInstanceBinder { public: GlobalStringKey GetBindingName()override { return GlobalStringKey::_Bind; } bool ApplicableToConstructorArgument()override { return false; } Ptr GenerateInstallStatement(GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, const WString& code, collections::List& errors)override { if (auto expression = Workflow_ParseExpression(L"bind(" + code + L")", errors)) { return Workflow_InstallBindProperty(variableName, propertyInfo, expression); } return 0; } }; /*********************************************************************** GuiFormatInstanceBinder (format) ***********************************************************************/ class GuiFormatInstanceBinder : public Object, public IGuiInstanceBinder { public: GlobalStringKey GetBindingName()override { return GlobalStringKey::_Format; } bool ApplicableToConstructorArgument()override { return false; } Ptr GenerateInstallStatement(GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, const WString& code, collections::List& errors)override { if (auto expression = Workflow_ParseExpression(L"bind($\"" + code + L"\")", errors)) { return Workflow_InstallBindProperty(variableName, propertyInfo, expression); } return 0; } }; /*********************************************************************** GuiEvalInstanceEventBinder (eval) ***********************************************************************/ class GuiEvalInstanceEventBinder : public Object, public IGuiInstanceEventBinder { public: GlobalStringKey GetBindingName()override { return GlobalStringKey::_Eval; } Ptr GenerateInstallStatement(GlobalStringKey variableName, description::IEventInfo* eventInfo, const WString& code, collections::List& errors)override { if (auto statement = Workflow_ParseStatement(code, errors)) { return Workflow_InstallEvalEvent(variableName, eventInfo, statement); } return 0; } }; /*********************************************************************** GuiPredefinedInstanceBindersPlugin ***********************************************************************/ class GuiPredefinedInstanceBindersPlugin : public Object, public IGuiPlugin { public: GuiPredefinedInstanceBindersPlugin() { } void Load()override { WfLoadTypes(); GuiIqLoadTypes(); } void AfterLoad()override { { IGuiParserManager* manager = GetParserManager(); manager->SetParsingTable(L"WORKFLOW", &WfLoadTable); manager->SetTableParser(L"WORKFLOW", L"WORKFLOW-EXPRESSION", &WfParseExpression); manager->SetTableParser(L"WORKFLOW", L"WORKFLOW-STATEMENT", &WfParseStatement); manager->SetTableParser(L"WORKFLOW", L"WORKFLOW-MODULE", &WfParseModule); manager->SetParsingTable(L"INSTANCE-QUERY", &GuiIqLoadTable); manager->SetTableParser(L"INSTANCE-QUERY", L"INSTANCE-QUERY", &GuiIqParse); } { IGuiInstanceLoaderManager* manager=GetInstanceLoaderManager(); manager->AddInstanceBinder(new GuiResourceInstanceBinder); manager->AddInstanceBinder(new GuiReferenceInstanceBinder); manager->AddInstanceBinder(new GuiEvalInstanceBinder); manager->AddInstanceEventBinder(new GuiEvalInstanceEventBinder); manager->AddInstanceBinder(new GuiBindInstanceBinder); manager->AddInstanceBinder(new GuiFormatInstanceBinder); } } void Unload()override { } }; GUI_REGISTER_PLUGIN(GuiPredefinedInstanceBindersPlugin) } } /*********************************************************************** GUIINSTANCELOADER_PREDEFINEDTYPERESOLVERS.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace parsing; using namespace parsing::xml; using namespace workflow::analyzer; using namespace workflow::runtime; using namespace reflection::description; using namespace collections; using namespace stream; using namespace controls; #define ERROR_CODE_PREFIX L"================================================================" /*********************************************************************** Instance Type Resolver (Instance) ***********************************************************************/ class GuiResourceInstanceTypeResolver : public Object , public IGuiResourceTypeResolver , private IGuiResourceTypeResolver_Precompile , private IGuiResourceTypeResolver_IndirectLoad { public: WString GetType()override { return L"Instance"; } bool XmlSerializable()override { return true; } bool StreamSerializable()override { return false; } WString GetPreloadType()override { return L"Xml"; } bool IsDelayLoad()override { return false; } vint GetMaxPassIndex()override { return 3; } void Precompile(Ptr resource, GuiResourcePrecompileContext& context, collections::List& errors)override { if (context.passIndex == 3) { if (auto obj = resource->GetContent().Cast()) { obj->ApplyStyles(context.resolver, errors); if (auto assembly = Workflow_PrecompileInstanceContext(obj, errors)) { auto compiled = MakePtr(); compiled->type = GuiInstanceCompiledWorkflow::InstanceCtor; compiled->classFullName = obj->className; compiled->assembly = assembly; context.targetFolder->CreateValueByPath(L"Workflow/InstanceCtor/" + resource->GetResourcePath(), L"Workflow", compiled); } } } } IGuiResourceTypeResolver_Precompile* Precompile()override { return this; } IGuiResourceTypeResolver_IndirectLoad* IndirectLoad()override { return this; } Ptr Serialize(Ptr resource)override { if (auto obj = resource.Cast()) { return obj->SaveToXml(); } return 0; } Ptr ResolveResource(Ptr resource, Ptr resolver, collections::List& errors)override { Ptr xml = resource.Cast(); if (xml) { Ptr context = GuiInstanceContext::LoadFromXml(xml, errors); return context; } return 0; } }; /*********************************************************************** Instance Style Type Resolver (InstanceStyle) ***********************************************************************/ class GuiResourceInstanceStyleResolver : public Object , public IGuiResourceTypeResolver , private IGuiResourceTypeResolver_IndirectLoad { public: WString GetType()override { return L"InstanceStyle"; } bool XmlSerializable()override { return true; } bool StreamSerializable()override { return false; } WString GetPreloadType()override { return L"Xml"; } bool IsDelayLoad()override { return false; } IGuiResourceTypeResolver_IndirectLoad* IndirectLoad()override { return this; } Ptr Serialize(Ptr resource)override { if (auto obj = resource.Cast()) { return obj->SaveToXml(); } return 0; } Ptr ResolveResource(Ptr resource, Ptr resolver, collections::List& errors)override { Ptr xml = resource.Cast(); if (xml) { auto context = GuiInstanceStyleContext::LoadFromXml(xml, errors); return context; } return 0; } }; /*********************************************************************** Shared Script Type Resolver (Script) ***********************************************************************/ class GuiResourceSharedScriptTypeResolver : public Object , public IGuiResourceTypeResolver , private IGuiResourceTypeResolver_Precompile , private IGuiResourceTypeResolver_IndirectLoad { public: WString GetType()override { return L"Script"; } bool XmlSerializable()override { return true; } bool StreamSerializable()override { return false; } WString GetPreloadType()override { return L"Xml"; } bool IsDelayLoad()override { return false; } vint GetMaxPassIndex()override { return 2; } void Precompile(Ptr resource, GuiResourcePrecompileContext& context, collections::List& errors)override { Ptr compiled; switch (context.passIndex) { case 0: { if (auto obj = resource->GetContent().Cast()) { WString path; GuiInstanceCompiledWorkflow::AssemblyType type = GuiInstanceCompiledWorkflow::Shared; if (obj->language == L"Workflow-ViewModel") { path = L"Workflow/ViewModel"; type = GuiInstanceCompiledWorkflow::ViewModel; } else if (obj->language == L"Workflow") { path = L"Workflow/Shared"; } if (path != L"") { compiled = context.targetFolder->GetValueByPath(path).Cast(); if (!compiled) { compiled = new GuiInstanceCompiledWorkflow; compiled->type = type; context.targetFolder->CreateValueByPath(path, L"Workflow", compiled); } } if (compiled) { compiled->codes.Add(obj->code); } } } return; case 1: { WString path = L"Workflow/ViewModel"; compiled = context.targetFolder->GetValueByPath(path).Cast(); } break; case 2: { WString path = L"Workflow/Shared"; compiled = context.targetFolder->GetValueByPath(path).Cast(); } break; default: return; } if (compiled) { auto table = GetParserManager()->GetParsingTable(L"WORKFLOW"); List> scriptErrors; compiled->assembly = Compile(table, compiled->codes, scriptErrors); compiled->codes.Clear(); if (scriptErrors.Count() > 0) { errors.Add(ERROR_CODE_PREFIX L"Failed to parse the shared workflow script"); FOREACH(Ptr, error, scriptErrors) { errors.Add( L"Row: " + itow(error->codeRange.start.row + 1) + L", Column: " + itow(error->codeRange.start.column + 1) + L", Message: " + error->errorMessage); } } else { compiled->Initialize(true); } } } IGuiResourceTypeResolver_Precompile* Precompile()override { return this; } IGuiResourceTypeResolver_IndirectLoad* IndirectLoad()override { return this; } Ptr Serialize(Ptr resource)override { if (auto obj = resource.Cast()) { return obj->SaveToXml(); } return 0; } Ptr ResolveResource(Ptr resource, Ptr resolver, collections::List& errors)override { Ptr xml = resource.Cast(); if (xml) { auto schema = GuiInstanceSharedScript::LoadFromXml(xml, errors); return schema; } return 0; } }; /*********************************************************************** Compiled Workflow Type Resolver (Script) ***********************************************************************/ class GuiResourceCompiledWorkflowTypeResolver : public Object , public IGuiResourceTypeResolver , private IGuiResourceTypeResolver_Initialize , private IGuiResourceTypeResolver_DirectLoadStream { public: WString GetType()override { return L"Workflow"; } bool XmlSerializable()override { return false; } bool StreamSerializable()override { return true; } vint GetMaxPassIndex()override { return 2; } void Initialize(Ptr resource, GuiResourceInitializeContext& context)override { if (auto compiled = resource->GetContent().Cast()) { switch (context.passIndex) { case 0: if (compiled->type == GuiInstanceCompiledWorkflow::ViewModel) { if (context.usage == GuiResourceUsage::DevelopmentTool) { compiled->Initialize(false); } } break; case 1: if (compiled->type == GuiInstanceCompiledWorkflow::Shared) { compiled->Initialize(true); } break; case 2: if (compiled->type == GuiInstanceCompiledWorkflow::InstanceCtor && compiled->type != GuiInstanceCompiledWorkflow::InstanceClass) { compiled->Initialize(false); } break; } } } IGuiResourceTypeResolver_Initialize* Initialize()override { return this; } IGuiResourceTypeResolver_DirectLoadStream* DirectLoadStream()override { return this; } void SerializePrecompiled(Ptr resource, stream::IStream& stream)override { if (auto obj = resource.Cast()) { internal::Writer writer(stream); vint type = (vint)obj->type; writer << type << obj->classFullName; MemoryStream memoryStream; obj->assembly->Serialize(memoryStream); writer << (IStream&)memoryStream; } } Ptr ResolveResourcePrecompiled(stream::IStream& stream, collections::List& errors)override { internal::Reader reader(stream); auto obj = MakePtr(); vint type; auto memoryStream = MakePtr();; reader << type << obj->classFullName << (IStream&)*memoryStream.Obj(); obj->type = (GuiInstanceCompiledWorkflow::AssemblyType)type; obj->binaryToLoad = memoryStream; return obj; } }; /*********************************************************************** Shared Script Type Resolver ***********************************************************************/ class GuiPredefinedTypeResolversPlugin : public Object, public IGuiPlugin { public: GuiPredefinedTypeResolversPlugin() { } void Load()override { } void AfterLoad()override { IGuiResourceResolverManager* manager = GetResourceResolverManager(); manager->SetTypeResolver(new GuiResourceInstanceTypeResolver); manager->SetTypeResolver(new GuiResourceInstanceStyleResolver); manager->SetTypeResolver(new GuiResourceSharedScriptTypeResolver); manager->SetTypeResolver(new GuiResourceCompiledWorkflowTypeResolver); } void Unload()override { } }; GUI_REGISTER_PLUGIN(GuiPredefinedTypeResolversPlugin) } } /*********************************************************************** GUIINSTANCEREPRESENTATION.CPP ***********************************************************************/ namespace vl { namespace presentation { using namespace collections; using namespace parsing; using namespace parsing::xml; using namespace templates; using namespace stream; /*********************************************************************** GuiTextRepr ***********************************************************************/ Ptr GuiTextRepr::Clone() { auto repr = MakePtr(); repr->fromStyle = fromStyle; repr->text = text; return repr; } void GuiTextRepr::FillXml(Ptr xml) { if (!fromStyle) { auto xmlText = MakePtr(); xmlText->content.value = text; xml->subNodes.Add(xmlText); } } /*********************************************************************** GuiAttSetterRepr ***********************************************************************/ void GuiAttSetterRepr::CloneBody(Ptr repr) { CopyFrom(repr->eventHandlers, eventHandlers); FOREACH_INDEXER(GlobalStringKey, name, index, setters.Keys()) { Ptr src = setters.Values()[index]; Ptr dst = new SetterValue; dst->binding = src->binding; FOREACH(Ptr, value, src->values) { dst->values.Add(value->Clone()); } repr->setters.Add(name, dst); } repr->instanceName = instanceName; } Ptr GuiAttSetterRepr::Clone() { auto repr = MakePtr(); repr->fromStyle = fromStyle; CloneBody(repr); return repr; } void GuiAttSetterRepr::FillXml(Ptr xml) { if (!fromStyle) { if (instanceName != GlobalStringKey::Empty) { auto attName = MakePtr(); attName->name.value = L"ref.Name"; attName->value.value = instanceName.ToString(); xml->attributes.Add(attName); } for (vint i = 0; i < setters.Count(); i++) { auto key = setters.Keys()[i]; auto value = setters.Values()[i]; if (key == GlobalStringKey::Empty) { FOREACH(Ptr, repr, value->values) { repr->FillXml(xml); } } else { bool containsElement = false; FOREACH(Ptr, repr, value->values) { if (!repr.Cast()) { containsElement = true; break; } } if (containsElement) { auto xmlProp = MakePtr(); xmlProp->name.value = L"att." + key.ToString(); if (value->binding != GlobalStringKey::Empty) { xmlProp->name.value += L"-" + value->binding.ToString(); } FOREACH(Ptr, repr, value->values) { if (!repr.Cast()) { repr->FillXml(xmlProp); } } xml->subNodes.Add(xmlProp); } else if (value->values.Count() > 0) { auto att = MakePtr(); att->name.value = key.ToString(); if (value->binding != GlobalStringKey::Empty) { att->name.value += L"-" + value->binding.ToString(); } att->value.value = value->values[0].Cast()->text; xml->attributes.Add(att); } } } for (vint i = 0; i < eventHandlers.Count(); i++) { auto key = eventHandlers.Keys()[i]; auto value = eventHandlers.Values()[i]; auto xmlEvent = MakePtr(); xmlEvent->name.value = L"ev." + key.ToString(); if (value->binding != GlobalStringKey::Empty) { xmlEvent->name.value += L"-" + value->binding.ToString(); } xml->subNodes.Add(xmlEvent); auto xmlText = MakePtr(); xmlText->content.value = value->value; xmlEvent->subNodes.Add(xmlText); } } } /*********************************************************************** GuiConstructorRepr ***********************************************************************/ Ptr GuiConstructorRepr::Clone() { auto repr = MakePtr(); repr->fromStyle = fromStyle; repr->typeNamespace = typeNamespace; repr->typeName = typeName; repr->styleName = styleName; CloneBody(repr); return repr; } void GuiConstructorRepr::FillXml(Ptr xml) { if (!fromStyle) { auto xmlCtor = MakePtr(); if (typeNamespace == GlobalStringKey::Empty) { xmlCtor->name.value = typeName.ToString(); } else { xmlCtor->name.value = typeNamespace.ToString() + L":" + typeName.ToString(); } if (styleName) { auto attStyle = MakePtr(); attStyle->name.value = L"ref.Style"; attStyle->value.value = styleName.Value(); xml->attributes.Add(attStyle); } GuiAttSetterRepr::FillXml(xmlCtor); xml->subNodes.Add(xmlCtor); } } /*********************************************************************** GuiInstanceContext ***********************************************************************/ void GuiInstanceContext::CollectDefaultAttributes(GuiAttSetterRepr::ValueList& values, Ptr xml, collections::List& errors) { if(auto parser=GetParserManager()->GetParser(L"INSTANCE-ELEMENT-NAME")) { // test if there is only one text value in the xml if(xml->subNodes.Count()==1) { if(Ptr text=xml->subNodes[0].Cast()) { Ptr value=new GuiTextRepr; value->text=text->content.value; values.Add(value); } else if(Ptr text=xml->subNodes[0].Cast()) { Ptr value=new GuiTextRepr; value->text=text->content.value; values.Add(value); } } // collect default attributes FOREACH(Ptr, element, XmlGetElements(xml)) { if(auto name=parser->TypedParse(element->name.value, errors)) { if(name->IsCtorName()) { // collect constructor values in the default attribute setter auto ctor=LoadCtor(element, errors); if(ctor) { values.Add(ctor); } } } } } } void GuiInstanceContext::CollectAttributes(GuiAttSetterRepr::SetteValuerMap& setters, Ptr xml, collections::List& errors) { if(auto parser=GetParserManager()->GetParser(L"INSTANCE-ELEMENT-NAME")) { Ptr defaultValue=new GuiAttSetterRepr::SetterValue; // collect default attributes CollectDefaultAttributes(defaultValue->values, xml, errors); if(defaultValue->values.Count()>0) { setters.Add(GlobalStringKey::Empty, defaultValue); } // collect values FOREACH(Ptr, element, XmlGetElements(xml)) { if (auto name = parser->TypedParse(element->name.value, errors)) { if(name->IsPropertyElementName()) { // collect a value as a new attribute setter if (setters.Keys().Contains(GlobalStringKey::Get(name->name))) { errors.Add(L"Duplicated attribute name \"" + name->name + L"\"."); } else { Ptr sv=new GuiAttSetterRepr::SetterValue; sv->binding = GlobalStringKey::Get(name->binding); if(name->binding==L"set") { // if the binding is "set", it means that this element is a complete setter element Ptr setter=new GuiAttSetterRepr; FillAttSetter(setter, element, errors); sv->values.Add(setter); } else { // if the binding is not "set", then this is a single-value attribute or a colection attribute // fill all data into this attribute CollectDefaultAttributes(sv->values, element, errors); } if(sv->values.Count()>0) { setters.Add(GlobalStringKey::Get(name->name), sv); } } } } } } } void GuiInstanceContext::CollectEvents(GuiAttSetterRepr::EventHandlerMap& eventHandlers, Ptr xml, collections::List& errors) { if(auto parser=GetParserManager()->GetParser(L"INSTANCE-ELEMENT-NAME")) { // collect values FOREACH(Ptr, element, XmlGetElements(xml)) { if(auto name=parser->TypedParse(element->name.value, errors)) { if(name->IsEventElementName()) { // collect a value as a new attribute setter if (eventHandlers.Keys().Contains(GlobalStringKey::Get(name->name))) { errors.Add(L"Duplicated event name \"" + name->name + L"\"."); } else { // test if there is only one text value in the xml if(element->subNodes.Count()==1) { if(Ptr text=element->subNodes[0].Cast()) { auto value = MakePtr(); value->binding = GlobalStringKey::Get(name->binding); value->value = text->content.value; eventHandlers.Add(GlobalStringKey::Get(name->name), value); } else if(Ptr text=element->subNodes[0].Cast()) { auto value = MakePtr(); value->binding = GlobalStringKey::Get(name->binding); value->value = text->content.value; eventHandlers.Add(GlobalStringKey::Get(name->name), value); } } } } } } } } void GuiInstanceContext::FillAttSetter(Ptr setter, Ptr xml, collections::List& errors) { if(auto parser=GetParserManager()->GetParser(L"INSTANCE-ELEMENT-NAME")) { // collect attributes as setters FOREACH(Ptr, att, xml->attributes) { if (auto name = parser->TypedParse(att->name.value, errors)) { if(name->IsReferenceAttributeName()) { // collect reference attributes if (name->name == L"Name") { setter->instanceName = GlobalStringKey::Get(att->value.value); } } else if(name->IsPropertyAttributeName()) { // collect attributes setters if (setter->setters.Keys().Contains(GlobalStringKey::Get(name->name))) { errors.Add(L"Duplicated attribute name \"" + name->name + L"\"."); } else { Ptr sv=new GuiAttSetterRepr::SetterValue; sv->binding=GlobalStringKey::Get(name->binding); setter->setters.Add(GlobalStringKey::Get(name->name), sv); Ptr value=new GuiTextRepr; value->text=att->value.value; sv->values.Add(value); } } else if (name->IsEventAttributeName()) { // collect event setters if (!setter->eventHandlers.Keys().Contains(GlobalStringKey::Get(name->name))) { auto value = MakePtr(); value->binding = GlobalStringKey::Get(name->binding); value->value = att->value.value; setter->eventHandlers.Add(GlobalStringKey::Get(name->name), value); } } } } // collect attributes and events CollectAttributes(setter->setters, xml, errors); CollectEvents(setter->eventHandlers, xml, errors); } } Ptr GuiInstanceContext::LoadCtor(Ptr xml, collections::List& errors) { if (auto parser = GetParserManager()->GetParser(L"INSTANCE-ELEMENT-NAME")) { if (auto name = parser->TypedParse(xml->name.value, errors)) { if(name->IsCtorName()) { Ptr ctor=new GuiConstructorRepr; ctor->typeNamespace = GlobalStringKey::Get(name->namespaceName); ctor->typeName = GlobalStringKey::Get(name->name); // collect attributes as setters FOREACH(Ptr, att, xml->attributes) { if(auto name=parser->TypedParse(att->name.value, errors)) if(name->IsReferenceAttributeName()) { if (name->name == L"Style") { ctor->styleName = att->value.value; } } } FillAttSetter(ctor, xml, errors); return ctor; } else { errors.Add(L"Wrong constructor name \"" + xml->name.value + L"\"."); } } } return 0; } Ptr GuiInstanceContext::LoadFromXml(Ptr xml, collections::List& errors) { Ptr context=new GuiInstanceContext; if(xml->rootElement->name.value==L"Instance") { if (auto codeBehindAttr = XmlGetAttribute(xml->rootElement, L"ref.CodeBehind")) { context->codeBehind = codeBehindAttr->value.value == L"true"; } // load type name if (auto classAttr = XmlGetAttribute(xml->rootElement, L"ref.Class")) { context->className = classAttr->value.value; } // load style names if (auto styleAttr = XmlGetAttribute(xml->rootElement, L"ref.Styles")) { SplitBySemicolon(styleAttr->value.value, context->stylePaths); } // load namespaces List> namespaceAttributes; CopyFrom(namespaceAttributes, xml->rootElement->attributes); if(!XmlGetAttribute(xml->rootElement, L"xmlns")) { Ptr att=new XmlAttribute; att->name.value=L"xmlns"; att->value.value = L"presentation::controls::Gui*;" L"presentation::elements::Gui*Element;" L"presentation::compositions::Gui*Composition;" L"presentation::compositions::Gui*;" L"presentation::templates::Gui*;" L"system::*;" L"system::reflection::*;" L"presentation::*;" L"presentation::Gui*;" L"presentation::controls::*;" L"presentation::controls::list::*;" L"presentation::controls::tree::*;" L"presentation::elements::*;" L"presentation::elements::Gui*;" L"presentation::elements::text*;" L"presentation::compositions::*;" L"presentation::templates::*"; namespaceAttributes.Add(att); } FOREACH(Ptr, att, namespaceAttributes) { // check if the attribute defines a namespace WString attName=att->name.value; if(attName.Length()>=5 && attName.Left(5)==L"xmlns") { GlobalStringKey ns; if(attName.Length()>6) { if(attName.Left(6)==L"xmlns:") { ns = GlobalStringKey::Get(attName.Sub(6, attName.Length() - 6)); } else { continue; } } // create a data structure for the namespace Ptr info; vint index=context->namespaces.Keys().IndexOf(ns); if(index==-1) { info=new NamespaceInfo; info->name=ns; context->namespaces.Add(ns, info); } else { info=context->namespaces.Values()[index]; } // extract all patterns in the namespace, split the value by ';' List patterns; SplitBySemicolon(att->value.value, patterns); FOREACH(WString, pattern, patterns) { // add the pattern to the namespace Ptr ns=new GuiInstanceNamespace; Pair star=INVLOC.FindFirst(pattern, L"*", Locale::None); if(star.key==-1) { ns->prefix=pattern; } else { ns->prefix=pattern.Sub(0, star.key); ns->postfix=pattern.Sub(star.key+star.value, pattern.Length()-star.key-star.value); } info->namespaces.Add(ns); } } } // load instance FOREACH(Ptr, element, XmlGetElements(xml->rootElement)) { if (element->name.value == L"ref.Parameter") { auto attName = XmlGetAttribute(element, L"Name"); auto attClass = XmlGetAttribute(element, L"Class"); if (attName && attClass) { auto parameter = MakePtr(); parameter->name = GlobalStringKey::Get(attName->value.value); parameter->className = GlobalStringKey::Get(attClass->value.value); context->parameters.Add(parameter); } } else if (element->name.value == L"ref.Property") { auto attName = XmlGetAttribute(element, L"Name"); auto attType = XmlGetAttribute(element, L"Type"); auto attReadonly = XmlGetAttribute(element, L"Readonly"); if (attName && attType) { auto prop = MakePtr(); prop->name = GlobalStringKey::Get(attName->value.value); prop->typeName = attType->value.value; if (attReadonly) { prop->readonly = attReadonly->value.value == L"true"; } context->properties.Add(prop); } } else if (element->name.value == L"ref.State") { auto attName = XmlGetAttribute(element, L"Name"); auto attType = XmlGetAttribute(element, L"Type"); auto attValue = XmlGetAttribute(element, L"Value"); if (attName && attType) { auto state = MakePtr(); state->name = GlobalStringKey::Get(attName->value.value); state->typeName = attType->value.value; if (attValue) { state->value = attValue->value.value; } context->states.Add(state); } } else if (!context->instance) { context->instance=LoadCtor(element, errors); } } } return context->instance ? context : nullptr; } Ptr GuiInstanceContext::SaveToXml() { auto xmlInstance = MakePtr(); xmlInstance->name.value = L"Instance"; { auto attCodeBehind = MakePtr(); attCodeBehind->name.value = L"ref.CodeBehind"; attCodeBehind->value.value = codeBehind ? L"true" : L"false"; xmlInstance->attributes.Add(attCodeBehind); } auto attClass = MakePtr(); attClass->name.value = L"ref.Class"; attClass->value.value = className; xmlInstance->attributes.Add(attClass); for (vint i = 0; i < namespaces.Count(); i++) { auto key = namespaces.Keys()[i]; auto value = namespaces.Values()[i]; auto xmlns = MakePtr(); xmlns->name.value = L"xmlns"; if (key != GlobalStringKey::Empty) { xmlns->name.value += L":" + key.ToString(); } xmlInstance->attributes.Add(xmlns); for (vint j = 0; j < value->namespaces.Count(); j++) { auto ns = value->namespaces[j]; if (j != 0) { xmlns->value.value += L";"; } xmlns->value.value += ns->prefix + L"*" + ns->postfix; } } FOREACH(Ptr, parameter, parameters) { auto xmlParameter = MakePtr(); xmlParameter->name.value = L"ref.Parameter"; xmlInstance->subNodes.Add(xmlParameter); auto attName = MakePtr(); attName->name.value = L"Name"; attName->value.value = parameter->name.ToString(); xmlParameter->attributes.Add(attName); auto attClass = MakePtr(); attClass->name.value = L"Class"; attClass->value.value = parameter->className.ToString(); xmlParameter->attributes.Add(attClass); } FOREACH(Ptr, prop, properties) { auto xmlProperty = MakePtr(); xmlProperty->name.value = L"ref.Property"; xmlInstance->subNodes.Add(xmlProperty); auto attName = MakePtr(); attName->name.value = L"Name"; attName->value.value = prop->name.ToString(); xmlProperty->attributes.Add(attName); auto attType = MakePtr(); attType->name.value = L"Type"; attType->value.value = prop->typeName; xmlProperty->attributes.Add(attType); auto attReadonly = MakePtr(); attReadonly->name.value = L"Readonly"; attReadonly->value.value = prop->readonly ? L"true" : L"false"; xmlProperty->attributes.Add(attReadonly); } FOREACH(Ptr, state, states) { auto xmlState = MakePtr(); xmlState->name.value = L"ref.State"; xmlInstance->subNodes.Add(xmlState); auto attName = MakePtr(); attName->name.value = L"Name"; attName->value.value = state->name.ToString(); xmlState->attributes.Add(attName); auto attType = MakePtr(); attType->name.value = L"Type"; attType->value.value = state->typeName; xmlState->attributes.Add(attType); if (state->value != L"") { auto attValue = MakePtr(); attValue->name.value = L"Value"; attValue->value.value = state->value; xmlState->attributes.Add(attType); } } if (stylePaths.Count() > 0) { auto attStyles = MakePtr(); attStyles->name.value = L"ref.Styles"; xmlInstance->attributes.Add(attStyles); for (vint j = 0; j < stylePaths.Count(); j++) { if (j != 0) { attStyles->value.value += L";"; } attStyles->value.value += stylePaths[j]; } } instance->FillXml(xmlInstance); auto doc = MakePtr(); doc->rootElement = xmlInstance; return doc; } bool GuiInstanceContext::ApplyStyles(Ptr resolver, collections::List& errors) { if (!appliedStyles) { appliedStyles = true; List> styles; FOREACH(WString, uri, stylePaths) { WString protocol, path; if (IsResourceUrl(uri, protocol, path)) { if (auto styleContext = resolver->ResolveResource(protocol, path).Cast()) { CopyFrom(styles, styleContext->styles, true); } else { errors.Add(L"Failed to find the style referred in attribute \"ref.Styles\": \"" + uri + L"\"."); } } else { errors.Add(L"Invalid path in attribute \"ref.Styles\": \"" + uri + L"\"."); } } FOREACH(Ptr, style, styles) { List> output; ExecuteQuery(style->query, this, output); FOREACH(Ptr, ctor, output) { ApplyStyle(style, ctor); } } return true; } else { return false; } } /*********************************************************************** GuiInstanceStyle ***********************************************************************/ namespace visitors { class SetStyleMarkVisitor : public Object, public GuiValueRepr::IVisitor { public: void Visit(GuiTextRepr* repr)override { repr->fromStyle = true; } void Visit(GuiAttSetterRepr* repr)override { repr->fromStyle = true; FOREACH(Ptr, value, repr->setters.Values()) { FOREACH(Ptr, subValue, value->values) { subValue->Accept(this); } } FOREACH(Ptr, value, repr->eventHandlers.Values()) { value->fromStyle = true; } } void Visit(GuiConstructorRepr* repr)override { Visit((GuiAttSetterRepr*)repr); } }; } using namespace visitors; Ptr GuiInstanceStyle::LoadFromXml(Ptr xml, collections::List& errors) { auto style = MakePtr(); if (auto pathAttr = XmlGetAttribute(xml, L"ref.Path")) { auto parser = GetParserManager()->GetParser(L"INSTANCE-QUERY"); if (auto query = parser->TypedParse(pathAttr->value.value, errors)) { style->query = query; } else { return 0; } } else { errors.Add(L"Missing attribute \"ref.Path\" in