mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-02-05 19:40:03 +08:00
13482 lines
459 KiB
C++
13482 lines
459 KiB
C++
/***********************************************************************
|
|
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
|
|
DEVELOPER: Zihan Chen(vczh)
|
|
***********************************************************************/
|
|
#include "GacUICompiler.h"
|
|
|
|
/***********************************************************************
|
|
.\GUICPPGEN.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace collections;
|
|
using namespace stream;
|
|
using namespace filesystem;
|
|
using namespace workflow;
|
|
using namespace workflow::cppcodegen;
|
|
|
|
bool WriteErrors(
|
|
collections::List<GuiResourceError>& errors,
|
|
const filesystem::FilePath& errorPath)
|
|
{
|
|
List<WString> output;
|
|
GuiResourceError::SortAndLog(errors, output);
|
|
return File(errorPath).WriteAllLines(output, true, BomEncoder::Utf8);
|
|
}
|
|
|
|
Ptr<GuiResourceFolder> PrecompileResource(
|
|
Ptr<GuiResource> resource,
|
|
GuiResourceCpuArchitecture targetCpuArchitecture,
|
|
IGuiResourcePrecompileCallback* callback,
|
|
collections::List<GuiResourceError>& errors)
|
|
{
|
|
auto precompiledFolder = resource->Precompile(targetCpuArchitecture, callback, errors);
|
|
return precompiledFolder;
|
|
}
|
|
|
|
Ptr<GuiInstanceCompiledWorkflow> WriteWorkflowScript(
|
|
Ptr<GuiResourceFolder> precompiledFolder,
|
|
const WString& assemblyResourcePath,
|
|
const filesystem::FilePath& workflowPath)
|
|
{
|
|
if (precompiledFolder)
|
|
{
|
|
if (auto compiled = precompiledFolder->GetValueByPath(assemblyResourcePath).Cast<GuiInstanceCompiledWorkflow>())
|
|
{
|
|
WString text;
|
|
if (compiled->assembly)
|
|
{
|
|
auto& codes = compiled->assembly->insAfterCodegen->moduleCodes;
|
|
for (auto [code, codeIndex] : indexed(codes))
|
|
{
|
|
text += L"================================(" + itow(codeIndex + 1) + L"/" + itow(codes.Count()) + L")================================\r\n";
|
|
text += code + L"\r\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (auto [moduleRecord, codeIndex] : indexed(compiled->modules))
|
|
{
|
|
WString code = GenerateToStream([&, module = moduleRecord.module](StreamWriter& writer)
|
|
{
|
|
WfPrint(module, L"", writer);
|
|
});
|
|
text += L"================================(" + itow(codeIndex + 1) + L"/" + itow(compiled->modules.Count()) + L")================================\r\n";
|
|
text += code + L"\r\n";
|
|
}
|
|
}
|
|
|
|
if (File(workflowPath).WriteAllText(text, true, BomEncoder::Utf8))
|
|
{
|
|
return compiled;
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<workflow::cppcodegen::WfCppOutput> WriteCppCodesToFile(
|
|
Ptr<GuiResource> resource,
|
|
Ptr<GuiInstanceCompiledWorkflow> compiled,
|
|
Ptr<workflow::cppcodegen::WfCppInput> cppInput,
|
|
const filesystem::FilePath& cppFolder,
|
|
collections::List<GuiResourceError>& errors)
|
|
{
|
|
auto output = GenerateCppFiles(cppInput, compiled->metadata.Obj());
|
|
|
|
if (compiled->metadata->errors.Count() > 0)
|
|
{
|
|
for (auto error : compiled->metadata->errors)
|
|
{
|
|
errors.Add(GuiResourceError({ {resource} }, error.message));
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
for (auto [fileName, index] : indexed(output->cppFiles.Keys()))
|
|
{
|
|
WString code = output->cppFiles.Values()[index];
|
|
File file(cppFolder / fileName);
|
|
|
|
if (file.Exists())
|
|
{
|
|
WString inputText;
|
|
BomEncoder::Encoding inputEncoding;
|
|
bool inputBom;
|
|
file.ReadAllTextWithEncodingTesting(inputText, inputEncoding, inputBom);
|
|
code = MergeCppFileContent(inputText, code);
|
|
}
|
|
|
|
if (file.Exists())
|
|
{
|
|
WString inputText;
|
|
BomEncoder::Encoding inputEncoding;
|
|
bool inputBom;
|
|
file.ReadAllTextWithEncodingTesting(inputText, inputEncoding, inputBom);
|
|
if (inputText == code)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
file.WriteAllText(code, true, BomEncoder::Utf8);
|
|
}
|
|
return output;
|
|
}
|
|
|
|
bool WriteBinaryResource(
|
|
Ptr<GuiResource> resource,
|
|
bool compress,
|
|
bool includeAssemblyInResource,
|
|
Nullable<filesystem::FilePath> resourceOutput,
|
|
Nullable<filesystem::FilePath> assemblyOutput)
|
|
{
|
|
auto precompiled = resource->GetFolder(L"Precompiled");
|
|
auto folder = precompiled->GetFolder(L"Workflow");
|
|
|
|
if (resourceOutput)
|
|
{
|
|
FileStream fileStream(resourceOutput.Value().GetFullPath(), FileStream::WriteOnly);
|
|
if (!fileStream.IsAvailable()) return false;
|
|
|
|
if (!includeAssemblyInResource) precompiled->RemoveFolder(L"Workflow");
|
|
if (compress)
|
|
{
|
|
LzwEncoder encoder;
|
|
EncoderStream encoderStream(fileStream, encoder);
|
|
resource->SavePrecompiledBinary(encoderStream);
|
|
}
|
|
else
|
|
{
|
|
resource->SavePrecompiledBinary(fileStream);
|
|
}
|
|
if (!includeAssemblyInResource) precompiled->AddFolder(L"Workflow", folder);
|
|
}
|
|
|
|
if (assemblyOutput)
|
|
{
|
|
if (auto item = folder->GetItem(L"InstanceClass"))
|
|
{
|
|
if (auto compiled = item->GetContent().Cast<GuiInstanceCompiledWorkflow>())
|
|
{
|
|
if (compiled->assembly)
|
|
{
|
|
FileStream fileStream(assemblyOutput.Value().GetFullPath(), FileStream::WriteOnly);
|
|
if (!fileStream.IsAvailable()) return false;
|
|
compiled->assembly->Serialize(fileStream);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void WriteEmbeddedBinaryClass(MemoryStream& binaryStream, bool compress, const WString& className, const WString& prefix, StreamWriter& writer)
|
|
{
|
|
MemoryStream compressedStream;
|
|
binaryStream.SeekFromBegin(0);
|
|
if (compress)
|
|
{
|
|
CompressStream(binaryStream, compressedStream);
|
|
}
|
|
else
|
|
{
|
|
CopyStream(binaryStream, compressedStream);
|
|
}
|
|
compressedStream.SeekFromBegin(0);
|
|
|
|
vint lengthBeforeCompressing = (vint)binaryStream.Size();
|
|
vint length = (vint)compressedStream.Size();
|
|
const vint block = 1024;
|
|
vint remain = length % block;
|
|
vint solidRows = length / block;
|
|
vint rows = solidRows + (remain ? 1 : 0);
|
|
|
|
#define PREFIX writer.WriteString(prefix);
|
|
|
|
PREFIX writer.WriteLine(L"class " + className);
|
|
PREFIX writer.WriteLine(L"{");
|
|
PREFIX writer.WriteLine(L"public:");
|
|
|
|
PREFIX writer.WriteLine(L"\tstatic const vint parserBufferLength = " + itow(length) + L"; // " + itow(lengthBeforeCompressing) + L" bytes before compressing");
|
|
PREFIX writer.WriteLine(L"\tstatic const vint parserBufferBlock = " + itow(block) + L";");
|
|
PREFIX writer.WriteLine(L"\tstatic const vint parserBufferRemain = " + itow(remain) + L";");
|
|
PREFIX writer.WriteLine(L"\tstatic const vint parserBufferRows = " + itow(rows) + L";");
|
|
PREFIX writer.WriteLine(L"\tstatic const char* parserBuffer[" + itow(rows) + L"];");
|
|
writer.WriteLine(L"");
|
|
|
|
PREFIX writer.WriteLine(L"\tstatic void ReadToStream(vl::stream::MemoryStream& stream)");
|
|
PREFIX writer.WriteLine(L"\t{");
|
|
PREFIX writer.WriteLine(L"\t\tDecompressStream(parserBuffer, " + WString(compress ? L"true" : L"false") + L", parserBufferRows, parserBufferBlock, parserBufferRemain, stream);");
|
|
PREFIX writer.WriteLine(L"\t}");
|
|
|
|
PREFIX writer.WriteLine(L"};");
|
|
writer.WriteLine(L"");
|
|
PREFIX writer.WriteLine(L"const char* " + className + L"::parserBuffer[] = {");
|
|
|
|
char buffer[block];
|
|
const wchar_t* hex = L"0123456789ABCDEF";
|
|
for (vint i = 0; i < rows; i++)
|
|
{
|
|
vint size = i == solidRows ? remain : block;
|
|
compressedStream.Read(buffer, size);
|
|
PREFIX writer.WriteString(L"\t\"");
|
|
for (vint j = 0; j < size; j++)
|
|
{
|
|
vuint8_t byte = buffer[j];
|
|
writer.WriteString(L"\\x");
|
|
writer.WriteChar(hex[byte / 16]);
|
|
writer.WriteChar(hex[byte % 16]);
|
|
}
|
|
writer.WriteLine(L"\",");
|
|
}
|
|
PREFIX writer.WriteLine(L"\t};");
|
|
|
|
#undef PREFIX
|
|
}
|
|
|
|
bool WriteEmbeddedResource(Ptr<GuiResource> resource,
|
|
Ptr<workflow::cppcodegen::WfCppInput> cppInput,
|
|
Ptr<workflow::cppcodegen::WfCppOutput> cppOutput,
|
|
bool compress,
|
|
const filesystem::FilePath& filePath)
|
|
{
|
|
WString code = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
writer.WriteLine(L"#include \"" + cppOutput->entryFileName + L".h\"");
|
|
writer.WriteLine(L"");
|
|
writer.WriteLine(L"namespace vl");
|
|
writer.WriteLine(L"{");
|
|
writer.WriteLine(L"\tnamespace presentation");
|
|
writer.WriteLine(L"\t{");
|
|
writer.WriteLine(L"\t\tnamespace user_resource");
|
|
writer.WriteLine(L"\t\t{");
|
|
writer.WriteLine(L"\t\t\tusing namespace collections;");
|
|
writer.WriteLine(L"\t\t\tusing namespace stream;");
|
|
writer.WriteLine(L"\t\t\tusing namespace controls;");
|
|
writer.WriteLine(L"");
|
|
|
|
{
|
|
MemoryStream resourceStream;
|
|
{
|
|
auto precompiled = resource->GetFolder(L"Precompiled");
|
|
auto folder = precompiled->GetFolder(L"Workflow");
|
|
precompiled->RemoveFolder(L"Workflow");
|
|
resource->SavePrecompiledBinary(resourceStream);
|
|
precompiled->AddFolder(L"Workflow", folder);
|
|
}
|
|
WriteEmbeddedBinaryClass(resourceStream, compress, cppInput->assemblyName + L"ResourceReader", L"\t\t\t", writer);
|
|
writer.WriteLine(L"");
|
|
}
|
|
{
|
|
writer.WriteLine(L"\t\t\tclass " + cppInput->assemblyName + L"ResourceLoaderPlugin : public Object, public IGuiPlugin");
|
|
writer.WriteLine(L"\t\t\t{");
|
|
writer.WriteLine(L"\t\t\tpublic:");
|
|
writer.WriteLine(L"");
|
|
writer.WriteLine(L"\t\t\t\tGUI_PLUGIN_NAME(GacGen_" + cppInput->assemblyName + L"ResourceLoader)");
|
|
writer.WriteLine(L"\t\t\t\t{");
|
|
writer.WriteLine(L"\t\t\t\t\tGUI_PLUGIN_DEPEND(GacUI_Res_Resource);");
|
|
writer.WriteLine(L"\t\t\t\t\tGUI_PLUGIN_DEPEND(GacUI_Res_TypeResolvers);");
|
|
writer.WriteLine(L"#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA");
|
|
writer.WriteLine(L"\t\t\t\t\tGUI_PLUGIN_DEPEND(GacUI_Instance_Reflection);");
|
|
writer.WriteLine(L"\t\t\t\t\tGUI_PLUGIN_DEPEND(GacUI_Compiler_WorkflowTypeResolvers);");
|
|
writer.WriteLine(L"#endif");
|
|
writer.WriteLine(L"\t\t\t\t}");
|
|
writer.WriteLine(L"");
|
|
writer.WriteLine(L"\t\t\t\tvoid Load()override");
|
|
writer.WriteLine(L"\t\t\t\t{");
|
|
writer.WriteLine(L"\t\t\t\t\tList<GuiResourceError> errors;");
|
|
writer.WriteLine(L"\t\t\t\t\tMemoryStream resourceStream;");
|
|
writer.WriteLine(L"\t\t\t\t\t" + cppInput->assemblyName + L"ResourceReader::ReadToStream(resourceStream);");
|
|
writer.WriteLine(L"\t\t\t\t\tresourceStream.SeekFromBegin(0);");
|
|
writer.WriteLine(L"\t\t\t\t\tGetResourceManager()->LoadResourceOrPending(resourceStream, GuiResourceUsage::InstanceClass);");
|
|
writer.WriteLine(L"\t\t\t\t}");
|
|
writer.WriteLine(L"");
|
|
writer.WriteLine(L"\t\t\t\tvoid Unload()override");
|
|
writer.WriteLine(L"\t\t\t\t{");
|
|
writer.WriteLine(L"\t\t\t\t}");
|
|
writer.WriteLine(L"\t\t\t};");
|
|
writer.WriteLine(L"\t\t\tGUI_REGISTER_PLUGIN(" + cppInput->assemblyName + L"ResourceLoaderPlugin)");
|
|
}
|
|
|
|
writer.WriteLine(L"\t\t}");
|
|
writer.WriteLine(L"\t}");
|
|
writer.WriteLine(L"}");
|
|
});
|
|
|
|
File file(filePath);
|
|
if (file.Exists())
|
|
{
|
|
WString inputText;
|
|
BomEncoder::Encoding inputEncoding;
|
|
bool inputBom;
|
|
file.ReadAllTextWithEncodingTesting(inputText, inputEncoding, inputBom);
|
|
if (inputText == code)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return file.WriteAllText(code, true, BomEncoder::Utf8);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\GUIINSTANCEANIMATION.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace reflection::description;
|
|
using namespace collections;
|
|
using namespace glr::xml;
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
using namespace presentation::controls;
|
|
|
|
/***********************************************************************
|
|
GuiInstanceGradientAnimation::LoadFromXml
|
|
***********************************************************************/
|
|
|
|
Ptr<GuiInstanceGradientAnimation> GuiInstanceGradientAnimation::LoadFromXml(Ptr<GuiResourceItem> resource, Ptr<glr::xml::XmlDocument> xml, GuiResourceError::List& errors)
|
|
{
|
|
auto animation = Ptr(new GuiInstanceGradientAnimation);
|
|
animation->tagPosition = { {resource},xml->rootElement->codeRange.start };
|
|
|
|
if (auto classAttr = XmlGetAttribute(xml->rootElement, L"ref.Class"))
|
|
{
|
|
animation->className = classAttr->value.value;
|
|
animation->classPosition = { {resource},classAttr->value.codeRange.start };
|
|
animation->classPosition.column += 1;
|
|
}
|
|
else
|
|
{
|
|
errors.Add({
|
|
{{resource},xml->rootElement->codeRange.start},
|
|
L"Precompile: Missing required attribute: \"ref.Class\"."
|
|
});
|
|
}
|
|
|
|
if (auto typeAttr = XmlGetAttribute(xml->rootElement, L"Type"))
|
|
{
|
|
animation->typeName = typeAttr->value.value;
|
|
animation->typePosition = { { resource },typeAttr->value.codeRange.start };
|
|
animation->typePosition.column += 1;
|
|
}
|
|
else
|
|
{
|
|
errors.Add({
|
|
{ { resource },xml->rootElement->codeRange.start },
|
|
L"Precompile: Missing required attribute: \"Type\"."
|
|
});
|
|
}
|
|
|
|
if (auto interpolationElement = XmlGetElement(xml->rootElement, L"Interpolation"))
|
|
{
|
|
if (auto cdata = interpolationElement->subNodes[0].Cast<XmlCData>())
|
|
{
|
|
animation->interpolation = cdata->content.value;
|
|
animation->interpolationPosition = { { resource },cdata->codeRange.start };
|
|
animation->interpolationPosition.column += 9; // <![CDATA[
|
|
}
|
|
else
|
|
{
|
|
errors.Add({
|
|
{ { resource },interpolationElement->codeRange.start },
|
|
L"Precompile: Interpolation function should be contained in a CDATA section."
|
|
});
|
|
}
|
|
}
|
|
|
|
if (auto targetsElement = XmlGetElement(xml->rootElement, L"Targets"))
|
|
{
|
|
for (auto targetElement : XmlGetElements(targetsElement, L"Target"))
|
|
{
|
|
Target target;
|
|
|
|
if (auto nameAttr = XmlGetAttribute(targetElement, L"Name"))
|
|
{
|
|
target.name = nameAttr->value.value;
|
|
target.namePosition = { { resource },nameAttr->value.codeRange.start };
|
|
target.namePosition.column += 1;
|
|
}
|
|
else
|
|
{
|
|
errors.Add({
|
|
{ { resource },targetElement->codeRange.start },
|
|
L"Precompile: Missing required attribute: \"Name\"."
|
|
});
|
|
}
|
|
|
|
if (auto interpolationElement = XmlGetElement(targetElement, L"Interpolation"))
|
|
{
|
|
if (auto cdata = interpolationElement->subNodes[0].Cast<XmlCData>())
|
|
{
|
|
target.interpolation = cdata->content.value;
|
|
target.interpolationPosition = { { resource },cdata->codeRange.start };
|
|
target.interpolationPosition.column += 9; // <
|
|
{
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = accessor(expression);
|
|
member->name.value = propInfo->GetName();
|
|
return member;
|
|
};
|
|
|
|
switch (td->GetTypeDescriptorFlags())
|
|
{
|
|
case TypeDescriptorFlags::Primitive:
|
|
callback(newAccessor, propInfo, originPropInfo);
|
|
break;
|
|
case TypeDescriptorFlags::Struct:
|
|
EnumerateMembers(callback, newAccessor, td, originPropInfo);
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
|
|
void GuiInstanceGradientAnimation::EnumerateMembers(EnumerateMemberCallback callback, EnumerateMemberAccessor accessor, description::ITypeDescriptor* td, description::IPropertyInfo* originPropInfo)
|
|
{
|
|
vint count = td->GetPropertyCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto propInfo = td->GetProperty(i);
|
|
if (propInfo->GetName() == L"value" && propInfo->GetOwnerTypeDescriptor() == description::GetTypeDescriptor<Color>())
|
|
{
|
|
continue;
|
|
}
|
|
EnumerateMembers(callback, accessor, propInfo, originPropInfo);
|
|
}
|
|
|
|
count = td->GetBaseTypeDescriptorCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
EnumerateMembers(callback, accessor, td->GetBaseTypeDescriptor(i), originPropInfo);
|
|
}
|
|
}
|
|
|
|
void GuiInstanceGradientAnimation::EnumerateProperties(EnumerateMemberCallback callback, description::ITypeDescriptor* td)
|
|
{
|
|
for (auto target : targets)
|
|
{
|
|
auto propInfo = td->GetPropertyByName(target.name, true);
|
|
EnumerateMembers(callback, [](auto x) {return x; }, propInfo, propInfo);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiInstanceGradientAnimation::InitStruct
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfExpression> GuiInstanceGradientAnimation::InitStruct(description::IPropertyInfo* propInfo, const WString& prefix, collections::SortedList<WString>& varNames)
|
|
{
|
|
auto td = propInfo->GetReturn()->GetTypeDescriptor();
|
|
auto name = prefix + L"_" + propInfo->GetName();
|
|
|
|
if (td->GetTypeDescriptorFlags() == TypeDescriptorFlags::Primitive)
|
|
{
|
|
if (!varNames.Contains(name))
|
|
{
|
|
return nullptr;
|
|
}
|
|
auto ref = Ptr(new WfReferenceExpression);
|
|
ref->name.value = L"<ani>" + name;
|
|
return ref;
|
|
}
|
|
else
|
|
{
|
|
List<ITypeDescriptor*> tds;
|
|
tds.Add(td);
|
|
auto ref = Ptr(new WfConstructorExpression);
|
|
|
|
for (vint i = 0; i < tds.Count(); i++)
|
|
{
|
|
auto currentTd = tds[i];
|
|
vint count = currentTd->GetBaseTypeDescriptorCount();
|
|
for (vint j = 0; j < count; j++)
|
|
{
|
|
tds.Add(currentTd->GetBaseTypeDescriptor(j));
|
|
}
|
|
|
|
count = currentTd->GetPropertyCount();
|
|
for (vint j = 0; j < count; j++)
|
|
{
|
|
auto currentPropInfo = currentTd->GetProperty(j);
|
|
if (auto expr = InitStruct(currentPropInfo, name, varNames))
|
|
{
|
|
auto pair = Ptr(new WfConstructorArgument);
|
|
|
|
auto refName = Ptr(new WfReferenceExpression);
|
|
refName->name.value = currentPropInfo->GetName();
|
|
|
|
pair->key = refName;
|
|
pair->value = expr;
|
|
ref->arguments.Add(pair);
|
|
}
|
|
}
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiInstanceGradientAnimation::Compile
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfModule> GuiInstanceGradientAnimation::Compile(GuiResourcePrecompileContext& precompileContext, const WString& moduleName, bool generateImpl, GuiResourceError::List& errors)
|
|
{
|
|
if (auto td = description::GetTypeDescriptor(typeName))
|
|
{
|
|
if (td->GetTypeDescriptorFlags() == TypeDescriptorFlags::Class)
|
|
{
|
|
{
|
|
if (auto ctorGroup = td->GetConstructorGroup())
|
|
{
|
|
vint count = ctorGroup->GetMethodCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto ctor = ctorGroup->GetMethod(i);
|
|
if (ctor->GetReturn()->GetDecorator() == ITypeInfo::SharedPtr && ctor->GetParameterCount() == 0)
|
|
{
|
|
goto CTOR_CHECK_PASS;
|
|
}
|
|
}
|
|
}
|
|
errors.Add({ typePosition,L"Precompile: Class \"" + typeName + L"\" should have a default constructor which returns a shared pointer and has no arguments." });
|
|
CTOR_CHECK_PASS:;
|
|
}
|
|
|
|
auto module = Ptr(new WfModule);
|
|
module->moduleType = WfModuleType::Module;
|
|
module->name.value = moduleName;
|
|
auto animationClass = Workflow_InstallClass(className, module);
|
|
|
|
auto typeInfo = Ptr(new SharedPtrTypeInfo(Ptr(new TypeDescriptorTypeInfo(td, TypeInfoHint::Normal))));
|
|
auto typeInfoDouble = CreateTypeInfoFromTypeFlag(TypeFlag::F8);
|
|
|
|
auto notImplemented = []()
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
auto stringExpr = Ptr(new WfStringExpression);
|
|
stringExpr->value.value = L"Not Implemented";
|
|
|
|
auto raiseStat = Ptr(new WfRaiseExceptionStatement);
|
|
raiseStat->expression = stringExpr;
|
|
|
|
block->statements.Add(raiseStat);
|
|
return block;
|
|
};
|
|
|
|
{
|
|
// prop Begin : <TYPE> = <DEFAULT> {}
|
|
auto prop = Ptr(new WfAutoPropertyDeclaration);
|
|
animationClass->declarations.Add(prop);
|
|
|
|
prop->functionKind = WfFunctionKind::Normal;
|
|
prop->name.value = L"Begin";
|
|
prop->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
prop->expression = CreateDefaultValue(typeInfo.Obj());
|
|
prop->configConst = WfAPConst::Writable;
|
|
prop->configObserve = WfAPObserve::Observable;
|
|
}
|
|
{
|
|
// prop End : <TYPE> = <DEFAULT> {}
|
|
auto prop = Ptr(new WfAutoPropertyDeclaration);
|
|
animationClass->declarations.Add(prop);
|
|
|
|
prop->functionKind = WfFunctionKind::Normal;
|
|
prop->name.value = L"End";
|
|
prop->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
prop->expression = CreateDefaultValue(typeInfo.Obj());
|
|
prop->configConst = WfAPConst::Writable;
|
|
prop->configObserve = WfAPObserve::Observable;
|
|
}
|
|
{
|
|
// prop Current : <TYPE> = <DEFAULT> {}
|
|
auto prop = Ptr(new WfAutoPropertyDeclaration);
|
|
animationClass->declarations.Add(prop);
|
|
|
|
prop->functionKind = WfFunctionKind::Normal;
|
|
prop->name.value = L"Current";
|
|
prop->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
prop->expression = CreateDefaultValue(typeInfo.Obj());
|
|
prop->configConst = WfAPConst::Writable;
|
|
prop->configObserve = WfAPObserve::Observable;
|
|
}
|
|
|
|
auto createIntVar = [&](const WString& name, const WString& interpolation, GuiResourceTextPos interpolationPosition)
|
|
{
|
|
// prop <ani-int> : (func(double):double) = <VALUE> {const, not observe}
|
|
auto var = Ptr(new WfVariableDeclaration);
|
|
animationClass->declarations.Add(var);
|
|
|
|
auto att = Ptr(new WfAttribute);
|
|
att->category.value = L"cpp";
|
|
att->name.value = L"Private";
|
|
var->attributes.Add(att);
|
|
|
|
var->name.value = L"<ani-int>" + name;
|
|
var->type = GetTypeFromTypeInfo(TypeInfoRetriver<Func<double(double)>>::CreateTypeInfo().Obj());
|
|
if (interpolation == L"" || !generateImpl)
|
|
{
|
|
auto ref = Ptr(new WfOrderedNameExpression);
|
|
ref->name.value = L"$1";
|
|
|
|
auto lambda = Ptr(new WfOrderedLambdaExpression);
|
|
lambda->body = ref;
|
|
|
|
var->expression = lambda;
|
|
}
|
|
else
|
|
{
|
|
var->expression = Workflow_ParseExpression(precompileContext, interpolationPosition.originalLocation, interpolation, interpolationPosition, errors);
|
|
}
|
|
};
|
|
createIntVar(L"", interpolation, interpolationPosition);
|
|
for (auto target : targets)
|
|
{
|
|
if (target.interpolation != L"")
|
|
{
|
|
createIntVar(target.name, target.interpolation, target.interpolationPosition);
|
|
}
|
|
}
|
|
|
|
List<IPropertyInfo*> props;
|
|
List<Ptr<WfExpression>> interpolations;
|
|
for (auto target : targets)
|
|
{
|
|
if (auto propInfo = td->GetPropertyByName(target.name, true))
|
|
{
|
|
if (!propInfo->GetGetter())
|
|
{
|
|
errors.Add({ target.namePosition,L"Precompile: Variable \"" + target.name + L"\" is not supported. An writable property with event is expected." });
|
|
}
|
|
else if (!propInfo->GetSetter())
|
|
{
|
|
errors.Add({ target.namePosition,L"Precompile: Readonly property \"" + target.name + L"\" is not supported. An writable property with event is expected." });
|
|
}
|
|
else if (!propInfo->GetValueChangedEvent())
|
|
{
|
|
errors.Add({ target.namePosition,L"Precompile: Property \"" + target.name + L"\" is not supported. An writable property with event is expected." });
|
|
}
|
|
ValidatePropertyType(target.namePosition, propInfo->GetReturn(), propInfo->GetName(), errors, true);
|
|
|
|
Ptr<WfExpression> interpolation;
|
|
if (target.interpolation != L"" && generateImpl)
|
|
{
|
|
interpolation = Workflow_ParseExpression(precompileContext, target.interpolationPosition.originalLocation, target.interpolation, target.interpolationPosition, errors);
|
|
}
|
|
|
|
props.Add(propInfo);
|
|
interpolations.Add(interpolation);
|
|
}
|
|
else
|
|
{
|
|
errors.Add({ target.namePosition,L"Precompile: Property \"" + target.name + L"\" does not exist." });
|
|
}
|
|
}
|
|
|
|
{
|
|
// func GetTimeScale(<ani>begin : <TYPE>, <ani>end : <TYPE>, <ani>current : <TYPE>) : double
|
|
auto func = Ptr(new WfFunctionDeclaration);
|
|
animationClass->declarations.Add(func);
|
|
|
|
func->functionKind = WfFunctionKind::Normal;
|
|
func->anonymity = WfFunctionAnonymity::Named;
|
|
func->name.value = L"GetTimeScale";
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>begin";
|
|
argument->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>end";
|
|
argument->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>current";
|
|
argument->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
func->returnType = GetTypeFromTypeInfo(typeInfoDouble.Obj());
|
|
|
|
if (generateImpl)
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
func->statement = block;
|
|
{
|
|
auto refZero = Ptr(new WfFloatingExpression);
|
|
refZero->value.value = L"0.0";
|
|
|
|
auto varScale = Ptr(new WfVariableDeclaration);
|
|
varScale->name.value = L"<ani>scale";
|
|
varScale->expression = refZero;
|
|
|
|
auto declStat = Ptr(new WfVariableStatement);
|
|
declStat->variable = varScale;
|
|
block->statements.Add(declStat);
|
|
}
|
|
EnumerateProperties([&](EnumerateMemberAccessor accessor, description::IPropertyInfo*, description::IPropertyInfo* propInfo)
|
|
{
|
|
auto subBlock = Ptr(new WfBlockStatement);
|
|
block->statements.Add(subBlock);
|
|
|
|
auto createVariable = [=](const WString& first, const WString& second, const WString& variable)
|
|
{
|
|
auto refBegin = Ptr(new WfReferenceExpression);
|
|
refBegin->name.value = first;
|
|
|
|
auto firstExpr = Ptr(new WfTypeCastingExpression);
|
|
firstExpr->expression = accessor(refBegin);
|
|
firstExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<double>::CreateTypeInfo().Obj());
|
|
firstExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
auto refEnd = Ptr(new WfReferenceExpression);
|
|
refEnd->name.value = second;
|
|
|
|
auto secondExpr = Ptr(new WfTypeCastingExpression);
|
|
secondExpr->expression = accessor(refEnd);
|
|
secondExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<double>::CreateTypeInfo().Obj());
|
|
secondExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
auto subExpr = Ptr(new WfBinaryExpression);
|
|
subExpr->first = firstExpr;
|
|
subExpr->second = secondExpr;
|
|
subExpr->op = WfBinaryOperator::Sub;
|
|
|
|
auto refAbs = Ptr(new WfChildExpression);
|
|
refAbs->parent = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Math>());
|
|
refAbs->name.value = L"Abs";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refAbs;
|
|
callExpr->arguments.Add(subExpr);
|
|
|
|
auto varRef = Ptr(new WfVariableDeclaration);
|
|
varRef->name.value = variable;
|
|
varRef->expression = callExpr;
|
|
|
|
auto declStat = Ptr(new WfVariableStatement);
|
|
declStat->variable = varRef;
|
|
subBlock->statements.Add(declStat);
|
|
};
|
|
createVariable(L"<ani>begin", L"<ani>end", L"<ani>ref");
|
|
createVariable(L"<ani>current", L"<ani>end", L"<ani>cur");
|
|
{
|
|
auto refRef = Ptr(new WfReferenceExpression);
|
|
refRef->name.value = L"<ani>ref";
|
|
|
|
auto refEpsilon = Ptr(new WfFloatingExpression);
|
|
refEpsilon->value.value = L"0.000001";
|
|
|
|
auto refMaxEpsilon = Ptr(new WfChildExpression);
|
|
refMaxEpsilon->parent = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Math>());
|
|
refMaxEpsilon->name.value = L"Max";
|
|
|
|
auto callExprEpsilon = Ptr(new WfCallExpression);
|
|
callExprEpsilon->function = refMaxEpsilon;
|
|
callExprEpsilon->arguments.Add(refRef);
|
|
callExprEpsilon->arguments.Add(refEpsilon);
|
|
|
|
auto refCur = Ptr(new WfReferenceExpression);
|
|
refCur->name.value = L"<ani>cur";
|
|
|
|
auto divExpr = Ptr(new WfBinaryExpression);
|
|
divExpr->first = refCur;
|
|
divExpr->second = callExprEpsilon;
|
|
divExpr->op = WfBinaryOperator::Div;
|
|
|
|
auto refMax = Ptr(new WfChildExpression);
|
|
refMax->parent = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Math>());
|
|
refMax->name.value = L"Max";
|
|
|
|
auto refScale = Ptr(new WfReferenceExpression);
|
|
refScale->name.value = L"<ani>scale";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refMax;
|
|
callExpr->arguments.Add(refScale);
|
|
callExpr->arguments.Add(divExpr);
|
|
|
|
auto refScale2 = Ptr(new WfReferenceExpression);
|
|
refScale2->name.value = L"<ani>scale";
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->first = refScale2;
|
|
assignExpr->second = callExpr;
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = assignExpr;
|
|
|
|
subBlock->statements.Add(exprStat);
|
|
}
|
|
}, td);
|
|
{
|
|
auto refOne = Ptr(new WfFloatingExpression);
|
|
refOne->value.value = L"1.0";
|
|
|
|
auto refScale = Ptr(new WfReferenceExpression);
|
|
refScale->name.value = L"<ani>scale";
|
|
|
|
auto refMin = Ptr(new WfChildExpression);
|
|
refMin->parent = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Math>());
|
|
refMin->name.value = L"Min";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refMin;
|
|
callExpr->arguments.Add(refOne);
|
|
callExpr->arguments.Add(refScale);
|
|
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = callExpr;
|
|
block->statements.Add(returnStat);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
func->statement = notImplemented();
|
|
}
|
|
}
|
|
{
|
|
// func Interpolate(<ani>begin : <TYPE>, <ani>end : <TYPE>, <ani>current : <TYPE>, <ani>ratio : double) : void
|
|
auto func = Ptr(new WfFunctionDeclaration);
|
|
animationClass->declarations.Add(func);
|
|
|
|
func->functionKind = WfFunctionKind::Normal;
|
|
func->anonymity = WfFunctionAnonymity::Named;
|
|
func->name.value = L"Interpolate";
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>begin";
|
|
argument->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>end";
|
|
argument->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>current";
|
|
argument->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>ratio";
|
|
argument->type = GetTypeFromTypeInfo(typeInfoDouble.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
func->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<void>::CreateTypeInfo().Obj());
|
|
|
|
if (generateImpl)
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
func->statement = block;
|
|
|
|
SortedList<WString> varNames;
|
|
|
|
EnumerateProperties([&](EnumerateMemberAccessor accessor, description::IPropertyInfo* propInfo, description::IPropertyInfo* originPropInfo)
|
|
{
|
|
WString intFunc = L"<ani-int>";
|
|
if (From(targets).Any([=](const Target& target)
|
|
{
|
|
return target.name == originPropInfo->GetName() && target.interpolation != L"";
|
|
}))
|
|
{
|
|
intFunc += originPropInfo->GetName();
|
|
}
|
|
|
|
Ptr<WfExpression> part1, part2, propChain;
|
|
{
|
|
auto refParent = Ptr(new WfReferenceExpression);
|
|
refParent->name.value = L"<ani>begin";
|
|
|
|
auto refProp = Ptr(new WfTypeCastingExpression);
|
|
refProp->expression = (propChain = accessor(refParent));
|
|
refProp->type = GetTypeFromTypeInfo(TypeInfoRetriver<double>::CreateTypeInfo().Obj());
|
|
refProp->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
auto refOne = Ptr(new WfFloatingExpression);
|
|
refOne->value.value = L"1.0";
|
|
|
|
auto refInt = Ptr(new WfReferenceExpression);
|
|
refInt->name.value = intFunc;
|
|
|
|
auto refRatio = Ptr(new WfReferenceExpression);
|
|
refRatio->name.value = L"<ani>ratio";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refInt;
|
|
callExpr->arguments.Add(refRatio);
|
|
|
|
auto subExpr = Ptr(new WfBinaryExpression);
|
|
subExpr->first = refOne;
|
|
subExpr->second = callExpr;
|
|
subExpr->op = WfBinaryOperator::Sub;
|
|
|
|
auto mulExpr = Ptr(new WfBinaryExpression);
|
|
mulExpr->first = refProp;
|
|
mulExpr->second = subExpr;
|
|
mulExpr->op = WfBinaryOperator::Mul;
|
|
|
|
part1 = mulExpr;
|
|
}
|
|
{
|
|
auto refParent = Ptr(new WfReferenceExpression);
|
|
refParent->name.value = L"<ani>end";
|
|
|
|
auto refProp = Ptr(new WfTypeCastingExpression);
|
|
refProp->expression = accessor(refParent);
|
|
refProp->type = GetTypeFromTypeInfo(TypeInfoRetriver<double>::CreateTypeInfo().Obj());
|
|
refProp->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
auto refInt = Ptr(new WfReferenceExpression);
|
|
refInt->name.value = intFunc;
|
|
|
|
auto refRatio = Ptr(new WfReferenceExpression);
|
|
refRatio->name.value = L"<ani>ratio";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refInt;
|
|
callExpr->arguments.Add(refRatio);
|
|
|
|
auto mulExpr = Ptr(new WfBinaryExpression);
|
|
mulExpr->first = refProp;
|
|
mulExpr->second = callExpr;
|
|
mulExpr->op = WfBinaryOperator::Mul;
|
|
|
|
part2 = mulExpr;
|
|
}
|
|
|
|
Ptr<WfExpression> exprMixed;
|
|
{
|
|
auto addExpr = Ptr(new WfBinaryExpression);
|
|
addExpr->first = part1;
|
|
addExpr->second = part2;
|
|
addExpr->op = WfBinaryOperator::Add;
|
|
|
|
if (propInfo->GetReturn()->GetTypeDescriptor() == description::GetTypeDescriptor<double>())
|
|
{
|
|
exprMixed = addExpr;
|
|
}
|
|
else if(propInfo->GetReturn()->GetTypeDescriptor() == description::GetTypeDescriptor<double>())
|
|
{
|
|
exprMixed = addExpr;
|
|
}
|
|
else
|
|
{
|
|
auto refRound = Ptr(new WfChildExpression);
|
|
refRound->parent = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Math>());
|
|
refRound->name.value = L"Round";
|
|
|
|
auto callRoundExpr = Ptr(new WfCallExpression);
|
|
callRoundExpr->function = refRound;
|
|
callRoundExpr->arguments.Add(addExpr);
|
|
|
|
exprMixed = callRoundExpr;
|
|
}
|
|
}
|
|
|
|
auto castExpr = Ptr(new WfTypeCastingExpression);
|
|
castExpr->expression = exprMixed;
|
|
castExpr->type = GetTypeFromTypeInfo(propInfo->GetReturn());
|
|
castExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
auto varRef = Ptr(new WfVariableDeclaration);
|
|
{
|
|
WString name = L"";
|
|
while (auto member = propChain.Cast<WfMemberExpression>())
|
|
{
|
|
name = L"_" + member->name.value + name;
|
|
propChain = member->parent;
|
|
}
|
|
varNames.Add(name);
|
|
varRef->name.value = L"<ani>" + name;
|
|
}
|
|
varRef->expression = castExpr;
|
|
|
|
auto declStat = Ptr(new WfVariableStatement);
|
|
declStat->variable = varRef;
|
|
block->statements.Add(declStat);
|
|
}, td);
|
|
|
|
for (auto target : targets)
|
|
{
|
|
auto refCurrent = Ptr(new WfReferenceExpression);
|
|
refCurrent->name.value = L"<ani>current";
|
|
|
|
auto refProp = Ptr(new WfMemberExpression);
|
|
refProp->parent = refCurrent;
|
|
refProp->name.value = target.name;
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->first = refProp;
|
|
assignExpr->second = InitStruct(td->GetPropertyByName(target.name, true), L"", varNames);
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = assignExpr;
|
|
block->statements.Add(exprStat);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
func->statement = notImplemented();
|
|
}
|
|
}
|
|
{
|
|
// func Interpolate(<ani>ratio : double) : void
|
|
auto func = Ptr(new WfFunctionDeclaration);
|
|
animationClass->declarations.Add(func);
|
|
|
|
func->functionKind = WfFunctionKind::Normal;
|
|
func->anonymity = WfFunctionAnonymity::Named;
|
|
func->name.value = L"Interpolate";
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>ratio";
|
|
argument->type = GetTypeFromTypeInfo(typeInfoDouble.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
func->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<void>::CreateTypeInfo().Obj());
|
|
|
|
if (generateImpl)
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
func->statement = block;
|
|
|
|
auto refBegin = Ptr(new WfReferenceExpression);
|
|
refBegin->name.value = L"Begin";
|
|
|
|
auto refEnd = Ptr(new WfReferenceExpression);
|
|
refEnd->name.value = L"End";
|
|
|
|
auto refCurrent = Ptr(new WfReferenceExpression);
|
|
refCurrent->name.value = L"Current";
|
|
|
|
auto refRatio = Ptr(new WfReferenceExpression);
|
|
refRatio->name.value = L"<ani>ratio";
|
|
|
|
auto refFunc = Ptr(new WfReferenceExpression);
|
|
refFunc->name.value = L"Interpolate";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refFunc;
|
|
callExpr->arguments.Add(refBegin);
|
|
callExpr->arguments.Add(refEnd);
|
|
callExpr->arguments.Add(refCurrent);
|
|
callExpr->arguments.Add(refRatio);
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = callExpr;
|
|
|
|
block->statements.Add(exprStat);
|
|
}
|
|
else
|
|
{
|
|
func->statement = notImplemented();
|
|
}
|
|
}
|
|
{
|
|
// func CreateAnimation(<ani>target : <TYPE>, <ani>time : UInt64) : IGuiAnimation^
|
|
auto func = Ptr(new WfFunctionDeclaration);
|
|
animationClass->declarations.Add(func);
|
|
|
|
func->functionKind = WfFunctionKind::Normal;
|
|
func->anonymity = WfFunctionAnonymity::Named;
|
|
func->name.value = L"CreateAnimation";
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>target";
|
|
argument->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>time";
|
|
argument->type = GetTypeFromTypeInfo(TypeInfoRetriver<vuint64_t>::CreateTypeInfo().Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
func->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<Ptr<IGuiAnimation>>::CreateTypeInfo().Obj());
|
|
|
|
if (generateImpl)
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
func->statement = block;
|
|
|
|
{
|
|
auto refEnd = Ptr(new WfReferenceExpression);
|
|
refEnd->name.value = L"End";
|
|
|
|
auto refTarget = Ptr(new WfReferenceExpression);
|
|
refTarget->name.value = L"<ani>target";
|
|
|
|
auto refCurrent = Ptr(new WfReferenceExpression);
|
|
refCurrent->name.value = L"Current";
|
|
|
|
auto refFunc = Ptr(new WfReferenceExpression);
|
|
refFunc->name.value = L"GetTimeScale";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refFunc;
|
|
callExpr->arguments.Add(refEnd);
|
|
callExpr->arguments.Add(refTarget);
|
|
callExpr->arguments.Add(refCurrent);
|
|
|
|
auto refTime = Ptr(new WfReferenceExpression);
|
|
refTime->name.value = L"<ani>time";
|
|
|
|
auto mulExpr = Ptr(new WfBinaryExpression);
|
|
mulExpr->first = refTime;
|
|
mulExpr->second = callExpr;
|
|
mulExpr->op = WfBinaryOperator::Mul;
|
|
|
|
auto refRound = Ptr(new WfChildExpression);
|
|
refRound->parent = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Math>());
|
|
refRound->name.value = L"Round";
|
|
|
|
auto callRoundExpr = Ptr(new WfCallExpression);
|
|
callRoundExpr->function = refRound;
|
|
callRoundExpr->arguments.Add(mulExpr);
|
|
|
|
auto castExpr = Ptr(new WfTypeCastingExpression);
|
|
castExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<vuint64_t>::CreateTypeInfo().Obj());
|
|
castExpr->expression = callRoundExpr;
|
|
castExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
auto varDecl = Ptr(new WfVariableDeclaration);
|
|
varDecl->name.value = L"<ani>scaledTime";
|
|
varDecl->expression = castExpr;
|
|
|
|
auto varStat = Ptr(new WfVariableStatement);
|
|
varStat->variable = varDecl;
|
|
block->statements.Add(varStat);
|
|
}
|
|
{
|
|
for (auto target : targets)
|
|
{
|
|
auto refBegin = Ptr(new WfReferenceExpression);
|
|
refBegin->name.value = L"Begin";
|
|
|
|
auto refBeginProp = Ptr(new WfMemberExpression);
|
|
refBeginProp->parent = refBegin;
|
|
refBeginProp->name.value = target.name;
|
|
|
|
auto refCurrent = Ptr(new WfReferenceExpression);
|
|
refCurrent->name.value = L"Current";
|
|
|
|
auto refCurrentProp = Ptr(new WfMemberExpression);
|
|
refCurrentProp->parent = refCurrent;
|
|
refCurrentProp->name.value = target.name;
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->first = refBeginProp;
|
|
assignExpr->second = refCurrentProp;
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = assignExpr;
|
|
|
|
block->statements.Add(exprStat);
|
|
}
|
|
}
|
|
{
|
|
auto refEnd = Ptr(new WfReferenceExpression);
|
|
refEnd->name.value = L"End";
|
|
|
|
auto refTarget = Ptr(new WfReferenceExpression);
|
|
refTarget->name.value = L"<ani>target";
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->first = refEnd;
|
|
assignExpr->second = refTarget;
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = assignExpr;
|
|
|
|
block->statements.Add(exprStat);
|
|
}
|
|
{
|
|
auto refCA = Ptr(new WfChildExpression);
|
|
refCA->parent = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<IGuiAnimation>());
|
|
refCA->name.value = L"CreateAnimation";
|
|
|
|
auto funcExpr = Ptr(new WfFunctionExpression);
|
|
{
|
|
auto funcDecl = Ptr(new WfFunctionDeclaration);
|
|
funcExpr->function = funcDecl;
|
|
|
|
funcDecl->functionKind = WfFunctionKind::Normal;
|
|
funcDecl->anonymity = WfFunctionAnonymity::Anonymous;
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>currentTime";
|
|
argument->type = GetTypeFromTypeInfo(TypeInfoRetriver<vuint64_t>::CreateTypeInfo().Obj());
|
|
funcDecl->arguments.Add(argument);
|
|
}
|
|
funcDecl->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<void>::CreateTypeInfo().Obj());
|
|
|
|
auto subBlock = Ptr(new WfBlockStatement);
|
|
funcDecl->statement = subBlock;
|
|
|
|
{
|
|
auto refCurrentTime = Ptr(new WfReferenceExpression);
|
|
refCurrentTime->name.value = L"<ani>currentTime";
|
|
|
|
auto firstExpr = Ptr(new WfTypeCastingExpression);
|
|
firstExpr->expression = refCurrentTime;
|
|
firstExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<double>::CreateTypeInfo().Obj());
|
|
firstExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
auto refTime = Ptr(new WfReferenceExpression);
|
|
refTime->name.value = L"<ani>time";
|
|
|
|
auto secondExpr = Ptr(new WfTypeCastingExpression);
|
|
secondExpr->expression = refTime;
|
|
secondExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<double>::CreateTypeInfo().Obj());
|
|
secondExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
auto divExpr = Ptr(new WfBinaryExpression);
|
|
divExpr->first = firstExpr;
|
|
divExpr->second = secondExpr;
|
|
divExpr->op = WfBinaryOperator::Div;
|
|
|
|
auto refInt = Ptr(new WfReferenceExpression);
|
|
refInt->name.value = L"Interpolate";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refInt;
|
|
callExpr->arguments.Add(divExpr);
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = callExpr;
|
|
|
|
subBlock->statements.Add(exprStat);
|
|
}
|
|
}
|
|
|
|
auto refTime = Ptr(new WfReferenceExpression);
|
|
refTime->name.value = L"<ani>time";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refCA;
|
|
callExpr->arguments.Add(funcExpr);
|
|
callExpr->arguments.Add(refTime);
|
|
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = callExpr;
|
|
|
|
block->statements.Add(returnStat);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
func->statement = notImplemented();
|
|
}
|
|
}
|
|
{
|
|
// new (<ani>current : <TYPE>)
|
|
auto func = Ptr(new WfConstructorDeclaration);
|
|
animationClass->declarations.Add(func);
|
|
|
|
func->constructorType = WfConstructorType::SharedPtr;
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ani>current";
|
|
argument->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
|
|
if (generateImpl)
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
func->statement = block;
|
|
|
|
{
|
|
List<WString> propNames;
|
|
propNames.Add(L"Begin");
|
|
propNames.Add(L"End");
|
|
propNames.Add(L"Current");
|
|
|
|
for (auto propName : propNames)
|
|
{
|
|
{
|
|
auto newExpr = Ptr(new WfNewClassExpression);
|
|
newExpr->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
|
|
auto refProp = Ptr(new WfReferenceExpression);
|
|
refProp->name.value = propName;
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->first = refProp;
|
|
assignExpr->second = newExpr;
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = assignExpr;
|
|
|
|
block->statements.Add(exprStat);
|
|
}
|
|
|
|
for (auto target : targets)
|
|
{
|
|
auto refProp = Ptr(new WfReferenceExpression);
|
|
refProp->name.value = propName;
|
|
|
|
auto refPropProp = Ptr(new WfMemberExpression);
|
|
refPropProp->parent = refProp;
|
|
refPropProp->name.value = target.name;
|
|
|
|
auto refCurrent = Ptr(new WfReferenceExpression);
|
|
refCurrent->name.value = L"<ani>current";
|
|
|
|
auto refCurrentProp = Ptr(new WfMemberExpression);
|
|
refCurrentProp->parent = refCurrent;
|
|
refCurrentProp->name.value = target.name;
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->first = refPropProp;
|
|
assignExpr->second = refCurrentProp;
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = assignExpr;
|
|
|
|
block->statements.Add(exprStat);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
func->statement = notImplemented();
|
|
}
|
|
}
|
|
|
|
return module;
|
|
}
|
|
else
|
|
{
|
|
errors.Add({ typePosition, L"Precompile: Type \"" + typeName + L"\" is not a class." });
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add({ typePosition, L"Precompile: Type \"" + typeName + L"\" does not exist." });
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\GUIINSTANCELOADER.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace collections;
|
|
using namespace glr ::xml;
|
|
using namespace controls;
|
|
using namespace regex;
|
|
using namespace reflection::description;
|
|
using namespace stream;
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
using namespace workflow::typeimpl;
|
|
|
|
/***********************************************************************
|
|
GuiInstancePropertyInfo
|
|
***********************************************************************/
|
|
|
|
Ptr<GuiInstancePropertyInfo> GuiInstancePropertyInfo::Unsupported()
|
|
{
|
|
return Ptr(new GuiInstancePropertyInfo);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GuiInstancePropertyInfo::Assign(Ptr<description::ITypeInfo> typeInfo)
|
|
{
|
|
auto info = Ptr(new GuiInstancePropertyInfo);
|
|
info->support = SupportAssign;
|
|
if (typeInfo) info->acceptableTypes.Add(typeInfo);
|
|
return info;
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GuiInstancePropertyInfo::AssignWithParent(Ptr<description::ITypeInfo> typeInfo)
|
|
{
|
|
auto info = Assign(typeInfo);
|
|
info->mergability = MergeWithParent;
|
|
return info;
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GuiInstancePropertyInfo::Collection(Ptr<description::ITypeInfo> typeInfo)
|
|
{
|
|
auto info = Assign(typeInfo);
|
|
info->support = SupportCollection;
|
|
return info;
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GuiInstancePropertyInfo::CollectionWithParent(Ptr<description::ITypeInfo> typeInfo)
|
|
{
|
|
auto info = Collection(typeInfo);
|
|
info->mergability = MergeWithParent;
|
|
return info;
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GuiInstancePropertyInfo::Set(Ptr<description::ITypeInfo> typeInfo)
|
|
{
|
|
auto info = Ptr(new GuiInstancePropertyInfo);
|
|
info->support = SupportSet;
|
|
if (typeInfo) info->acceptableTypes.Add(typeInfo);
|
|
return info;
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GuiInstancePropertyInfo::Array(Ptr<description::ITypeInfo> typeInfo)
|
|
{
|
|
auto info = Ptr(new GuiInstancePropertyInfo);
|
|
info->support = SupportArray;
|
|
if (typeInfo) info->acceptableTypes.Add(typeInfo);
|
|
return info;
|
|
}
|
|
|
|
/***********************************************************************
|
|
IGuiInstanceLoader
|
|
***********************************************************************/
|
|
|
|
void IGuiInstanceLoader::ClearReflectionCache()
|
|
{
|
|
}
|
|
|
|
void IGuiInstanceLoader::GetRequiredPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)
|
|
{
|
|
}
|
|
|
|
void IGuiInstanceLoader::GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)
|
|
{
|
|
}
|
|
|
|
void IGuiInstanceLoader::GetPairedProperties(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo, collections::List<GlobalStringKey>& propertyNames)
|
|
{
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> IGuiInstanceLoader::GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
bool IGuiInstanceLoader::CanCreate(const TypeInfo& typeInfo)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Ptr<workflow::WfBaseConstructorCall> IGuiInstanceLoader::CreateRootInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, ArgumentMap& arguments, GuiResourceError::List& errors)
|
|
{
|
|
CHECK_FAIL(L"IGuiInstanceLoader::CreateRootInstance(GuiResourcePrecompileContext&, types::ResolvingResult&, const TypeInfo&, Ptr<workflow::WfExpression>, ArgumentMap&, GuiResourceError::List&)#This function is not implemented.");
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> IGuiInstanceLoader::InitializeRootInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceError::List& errors)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> IGuiInstanceLoader::CreateInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos tagPosition, GuiResourceError::List& errors)
|
|
{
|
|
CHECK_FAIL(L"IGuiInstanceLoader::CreateInstance(GuiResourcePrecompileContext&, types::ResolvingResult&, const TypeInfo&, GlobalStringKey, ArgumentMap&, GuiResourceTextPos, GuiResourceError::List&)#This function is not implemented.");
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> IGuiInstanceLoader::AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)
|
|
{
|
|
CHECK_FAIL(L"IGuiInstanceLoader::AssignParameters(GuiResourcePrecompileContext&, types::ResolvingResult&, const TypeInfo&, GlobalStringKey, ArgumentMap&, GuiResourceTextPos, GuiResourceError::List&)#This function is not implemented.");
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> IGuiInstanceLoader::GetParameter(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const PropertyInfo& propertyInfo, GlobalStringKey variableName, GuiResourceTextPos attPosition, GuiResourceError::List& errors)
|
|
{
|
|
CHECK_FAIL(L"IGuiInstanceLoader::GetParameter(GuiResourcePrecompileContext&, types::ResolvingResult&, const PropertyInfo&, GlobalStringKey, GuiResourceTextPos, GuiResourceError::List&)#This function is not implemented.");
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiInstanceContext::ElementName Parser
|
|
***********************************************************************/
|
|
|
|
class GuiInstanceContextElementNameParser : public Object, public IGuiParser<GuiInstanceContext::ElementName>
|
|
{
|
|
typedef GuiInstanceContext::ElementName ElementName;
|
|
public:
|
|
Regex regexElementName;
|
|
const vint _namespaceName;
|
|
const vint _category;
|
|
const vint _name;
|
|
const vint _binding;
|
|
|
|
GuiInstanceContextElementNameParser()
|
|
: regexElementName(L"((<namespaceName>[a-zA-Z_]/w*):)?((<category>[a-zA-Z_]/w*).)?(<name>[a-zA-Z_]/w*)(-(<binding>[a-zA-Z_]/w*))?")
|
|
, _namespaceName(regexElementName.CaptureNames().IndexOf(L"namespaceName"))
|
|
, _category(regexElementName.CaptureNames().IndexOf(L"category"))
|
|
, _name(regexElementName.CaptureNames().IndexOf(L"name"))
|
|
, _binding(regexElementName.CaptureNames().IndexOf(L"binding"))
|
|
{
|
|
}
|
|
|
|
Ptr<ElementName> ParseInternal(const WString& text, collections::List<glr::ParsingError>& errors)override
|
|
{
|
|
Ptr<RegexMatch> match = regexElementName.MatchHead(text);
|
|
if (!match || match->Result().Length() != text.Length())
|
|
{
|
|
glr::ParsingError error;
|
|
error.message = L"Failed to parse an element name \"" + text + L"\".";
|
|
errors.Add(error);
|
|
return nullptr;
|
|
}
|
|
|
|
auto elementName = Ptr(new ElementName);
|
|
if (match->Groups().Keys().Contains(_namespaceName))
|
|
{
|
|
elementName->namespaceName = match->Groups()[_namespaceName][0].Value();
|
|
}
|
|
if (match->Groups().Keys().Contains(_category))
|
|
{
|
|
elementName->category = match->Groups()[_category][0].Value();
|
|
}
|
|
if (match->Groups().Keys().Contains(_name))
|
|
{
|
|
elementName->name = match->Groups()[_name][0].Value();
|
|
}
|
|
if (match->Groups().Keys().Contains(_binding))
|
|
{
|
|
elementName->binding = match->Groups()[_binding][0].Value();
|
|
}
|
|
return elementName;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiDefaultInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define CTOR_PARAM_PREFIX\
|
|
static const wchar_t Prefix[] = L"<ctor-parameter>";\
|
|
static const vint PrefixLength = (vint)sizeof(Prefix) / sizeof(*Prefix) - 1;\
|
|
|
|
#define CTOR_PARAM_NAME(NAME) (NAME).Right((NAME).Length() - PrefixLength)
|
|
|
|
class GuiDefaultInstanceLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
typedef Tuple<ITypeDescriptor*, GlobalStringKey> FieldKey;
|
|
typedef Tuple<Ptr<GuiInstancePropertyInfo>, IPropertyInfo*> PropertyType;
|
|
|
|
Dictionary<FieldKey, PropertyType> propertyTypes;
|
|
Dictionary<ITypeDescriptor*, IMethodInfo*> defaultConstructors;
|
|
Dictionary<ITypeDescriptor*, IMethodInfo*> instanceConstructors;
|
|
public:
|
|
IMethodInfo* GetDefaultConstructor(ITypeDescriptor* typeDescriptor)
|
|
{
|
|
IMethodInfo* ctor = nullptr;
|
|
vint index = defaultConstructors.Keys().IndexOf(typeDescriptor);
|
|
if (index == -1)
|
|
{
|
|
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)
|
|
{
|
|
ctor = method;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
defaultConstructors.Add(typeDescriptor, ctor);
|
|
}
|
|
else
|
|
{
|
|
ctor = defaultConstructors.Values()[index];
|
|
}
|
|
return ctor;
|
|
}
|
|
|
|
IMethodInfo* GetInstanceConstructor(ITypeDescriptor* typeDescriptor)
|
|
{
|
|
CTOR_PARAM_PREFIX
|
|
|
|
IMethodInfo* ctor = nullptr;
|
|
vint index = instanceConstructors.Keys().IndexOf(typeDescriptor);
|
|
if (index == -1)
|
|
{
|
|
if (dynamic_cast<WfClass*>(typeDescriptor))
|
|
{
|
|
if (auto group = typeDescriptor->GetConstructorGroup())
|
|
{
|
|
if (group->GetMethodCount() == 1)
|
|
{
|
|
auto method = group->GetMethod(0);
|
|
vint count = method->GetParameterCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
const auto& name = method->GetParameter(i)->GetName();
|
|
if (name.Length() <= PrefixLength || name.Left(PrefixLength) != Prefix)
|
|
{
|
|
goto FINISHED;
|
|
}
|
|
|
|
if (!typeDescriptor->GetPropertyByName(CTOR_PARAM_NAME(name), false))
|
|
{
|
|
goto FINISHED;
|
|
}
|
|
}
|
|
ctor = method;
|
|
}
|
|
}
|
|
}
|
|
FINISHED:
|
|
instanceConstructors.Add(typeDescriptor, ctor);
|
|
}
|
|
else
|
|
{
|
|
ctor = instanceConstructors.Values()[index];
|
|
}
|
|
return ctor;
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return GlobalStringKey::Empty;
|
|
}
|
|
|
|
void ClearReflectionCache()override
|
|
{
|
|
propertyTypes.Clear();
|
|
defaultConstructors.Clear();
|
|
instanceConstructors.Clear();
|
|
}
|
|
|
|
//***********************************************************************************
|
|
|
|
ITypeInfo* ProcessGenericType(ITypeInfo* propType, bool& readableList, bool& writableList, bool& collectionType)
|
|
{
|
|
readableList = false;
|
|
writableList = false;
|
|
collectionType = false;
|
|
if (propType->GetDecorator() == ITypeInfo::SharedPtr && propType->GetElementType()->GetDecorator() == ITypeInfo::Generic)
|
|
{
|
|
auto genericType = propType->GetElementType();
|
|
if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor<IValueList>())
|
|
{
|
|
readableList = true;
|
|
writableList = true;
|
|
collectionType = true;
|
|
return genericType->GetGenericArgument(0);
|
|
}
|
|
else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor<IValueObservableList>())
|
|
{
|
|
readableList = true;
|
|
writableList = true;
|
|
collectionType = true;
|
|
return genericType->GetGenericArgument(0);
|
|
}
|
|
else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor<IValueEnumerator>())
|
|
{
|
|
collectionType = true;
|
|
return genericType->GetGenericArgument(0);
|
|
}
|
|
else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor<IValueEnumerable>())
|
|
{
|
|
readableList = true;
|
|
collectionType = true;
|
|
return genericType->GetGenericArgument(0);
|
|
}
|
|
else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor<IValueReadonlyList>())
|
|
{
|
|
readableList = true;
|
|
collectionType = true;
|
|
return genericType->GetGenericArgument(0);
|
|
}
|
|
else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor<IValueReadonlyDictionary>())
|
|
{
|
|
collectionType = true;
|
|
return nullptr;
|
|
}
|
|
else if (genericType->GetTypeDescriptor() == description::GetTypeDescriptor<IValueDictionary>())
|
|
{
|
|
collectionType = true;
|
|
return nullptr;
|
|
}
|
|
}
|
|
return propType;
|
|
}
|
|
|
|
ITypeInfo* GetPropertyReflectionTypeInfo(const PropertyInfo& propertyInfo, GuiInstancePropertyInfo::Support& support)
|
|
{
|
|
support = GuiInstancePropertyInfo::NotSupport;
|
|
IPropertyInfo* prop = propertyInfo.typeInfo.typeInfo->GetTypeDescriptor()->GetPropertyByName(propertyInfo.propertyName.ToString(), true);
|
|
if (prop)
|
|
{
|
|
ITypeInfo* propType = prop->GetReturn();
|
|
bool readableList = false;
|
|
bool writableList = false;
|
|
bool collectionType = false;
|
|
auto propValueType = ProcessGenericType(propType, readableList, writableList, collectionType);
|
|
|
|
if (prop->IsWritable())
|
|
{
|
|
if (collectionType)
|
|
{
|
|
if (readableList)
|
|
{
|
|
support = GuiInstancePropertyInfo::SupportArray;
|
|
return propValueType;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
support = GuiInstancePropertyInfo::SupportAssign;
|
|
return propValueType;
|
|
}
|
|
}
|
|
else if (prop->IsReadable())
|
|
{
|
|
if (collectionType)
|
|
{
|
|
if (writableList)
|
|
{
|
|
support = GuiInstancePropertyInfo::SupportCollection;
|
|
return propValueType;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (propType->GetDecorator() == ITypeInfo::SharedPtr || propType->GetDecorator() == ITypeInfo::RawPtr)
|
|
{
|
|
if (propType->GetElementType()->GetDecorator() != ITypeInfo::Generic)
|
|
{
|
|
support = GuiInstancePropertyInfo::SupportSet;
|
|
return propValueType;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void CollectPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, ITypeDescriptor* typeDescriptor, collections::List<GlobalStringKey>& 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(precompileContext, PropertyInfo(typeInfo, propertyName));
|
|
if (info && info->support != GuiInstancePropertyInfo::NotSupport)
|
|
{
|
|
propertyNames.Add(propertyName);
|
|
}
|
|
}
|
|
}
|
|
|
|
vint parentCount = typeDescriptor->GetBaseTypeDescriptorCount();
|
|
for (vint i = 0; i < parentCount; i++)
|
|
{
|
|
CollectPropertyNames(precompileContext, typeInfo, typeDescriptor->GetBaseTypeDescriptor(i), propertyNames);
|
|
}
|
|
}
|
|
|
|
//***********************************************************************************
|
|
|
|
void GetRequiredPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
CTOR_PARAM_PREFIX
|
|
|
|
if (auto ctor = GetInstanceConstructor(typeInfo.typeInfo->GetTypeDescriptor()))
|
|
{
|
|
vint count = ctor->GetParameterCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
const auto& name = ctor->GetParameter(i)->GetName();
|
|
propertyNames.Add(GlobalStringKey::Get(CTOR_PARAM_NAME(name)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
CollectPropertyNames(precompileContext, typeInfo, typeInfo.typeInfo->GetTypeDescriptor(), propertyNames);
|
|
}
|
|
|
|
PropertyType GetPropertyTypeCached(const PropertyInfo& propertyInfo)
|
|
{
|
|
CTOR_PARAM_PREFIX
|
|
|
|
FieldKey key(propertyInfo.typeInfo.typeInfo->GetTypeDescriptor(), propertyInfo.propertyName);
|
|
vint index = propertyTypes.Keys().IndexOf(key);
|
|
if (index == -1)
|
|
{
|
|
GuiInstancePropertyInfo::Support support = GuiInstancePropertyInfo::NotSupport;
|
|
if (ITypeInfo* propType = GetPropertyReflectionTypeInfo(propertyInfo, support))
|
|
{
|
|
auto result = Ptr(new GuiInstancePropertyInfo);
|
|
result->support = support;
|
|
result->acceptableTypes.Add(CopyTypeInfo(propType));
|
|
|
|
if (auto ctor = GetInstanceConstructor(propertyInfo.typeInfo.typeInfo->GetTypeDescriptor()))
|
|
{
|
|
vint count = ctor->GetParameterCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
const auto& name = ctor->GetParameter(i)->GetName();
|
|
if (CTOR_PARAM_NAME(name) == propertyInfo.propertyName.ToString())
|
|
{
|
|
result->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
result->bindability = GuiInstancePropertyInfo::Bindable;
|
|
}
|
|
}
|
|
}
|
|
|
|
IPropertyInfo* prop = propertyInfo.typeInfo.typeInfo->GetTypeDescriptor()->GetPropertyByName(propertyInfo.propertyName.ToString(), true);
|
|
PropertyType value(result, prop);
|
|
propertyTypes.Add(key, value);
|
|
return value;
|
|
}
|
|
else
|
|
{
|
|
PropertyType value(GuiInstancePropertyInfo::Unsupported(), nullptr);
|
|
propertyTypes.Add(key, value);
|
|
return value;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return propertyTypes.Values()[index];
|
|
}
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
return GetPropertyTypeCached(propertyInfo).get<0>();
|
|
}
|
|
|
|
//***********************************************************************************
|
|
|
|
bool CanCreate(const TypeInfo& typeInfo)override
|
|
{
|
|
return
|
|
GetDefaultConstructor(typeInfo.typeInfo->GetTypeDescriptor()) != nullptr ||
|
|
GetInstanceConstructor(typeInfo.typeInfo->GetTypeDescriptor()) != nullptr;
|
|
}
|
|
|
|
Ptr<workflow::WfBaseConstructorCall> CreateRootInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, ArgumentMap& arguments, GuiResourceError::List& errors)override
|
|
{
|
|
CTOR_PARAM_PREFIX
|
|
|
|
if (arguments.Count() > 0)
|
|
{
|
|
auto call = Ptr(new WfBaseConstructorCall);
|
|
|
|
auto baseTd = typeInfo.typeInfo->GetTypeDescriptor()->GetBaseTypeDescriptor(0);
|
|
auto baseTypeInfo = Ptr(new TypeDescriptorTypeInfo(baseTd, TypeInfoHint::Normal));
|
|
call->type = GetTypeFromTypeInfo(baseTypeInfo.Obj());
|
|
|
|
auto ctor = baseTd->GetConstructorGroup()->GetMethod(0);
|
|
vint count = ctor->GetParameterCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto key = GlobalStringKey::Get(CTOR_PARAM_NAME(ctor->GetParameter(0)->GetName()));
|
|
|
|
vint index = arguments.Keys().IndexOf(key);
|
|
if (index == -1)
|
|
{
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
call->arguments.Add(arguments.GetByIndex(index)[0].expression);
|
|
}
|
|
}
|
|
return call;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> CreateInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos tagPosition, GuiResourceError::List& errors)override
|
|
{
|
|
CTOR_PARAM_PREFIX
|
|
auto defaultCtor = GetDefaultConstructor(typeInfo.typeInfo->GetTypeDescriptor());
|
|
auto instanceCtor = GetInstanceConstructor(typeInfo.typeInfo->GetTypeDescriptor());
|
|
|
|
auto create = Ptr(new WfNewClassExpression);
|
|
if (defaultCtor)
|
|
{
|
|
create->type = GetTypeFromTypeInfo(defaultCtor->GetReturn());
|
|
}
|
|
else
|
|
{
|
|
create->type = GetTypeFromTypeInfo(instanceCtor->GetReturn());
|
|
|
|
vint count = instanceCtor->GetParameterCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
const auto& name = instanceCtor->GetParameter(i)->GetName();
|
|
auto key = GlobalStringKey::Get(CTOR_PARAM_NAME(name));
|
|
|
|
vint index = arguments.Keys().IndexOf(key);
|
|
if (index == -1)
|
|
{
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
create->arguments.Add(arguments.GetByIndex(index)[0].expression);
|
|
}
|
|
}
|
|
}
|
|
|
|
auto refValue = Ptr(new WfReferenceExpression);
|
|
refValue->name.value = variableName.ToString();
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refValue;
|
|
assign->second = create;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
return stat;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
PropertyType propertyType = GetPropertyTypeCached(PropertyInfo(typeInfo, prop));
|
|
if (propertyType.get<1>())
|
|
{
|
|
switch (propertyType.get<0>()->support)
|
|
{
|
|
case GuiInstancePropertyInfo::SupportCollection:
|
|
{
|
|
const auto& values = arguments.GetByIndex(index);
|
|
if (values.Count() > 0)
|
|
{
|
|
{
|
|
auto refValue = Ptr(new WfReferenceExpression);
|
|
refValue->name.value = variableName.ToString();
|
|
|
|
auto refProp = Ptr(new WfMemberExpression);
|
|
refProp->parent = refValue;
|
|
refProp->name.value = prop.ToString();
|
|
|
|
auto varDesc = Ptr(new WfVariableDeclaration);
|
|
varDesc->name.value = L"<collection>";
|
|
varDesc->expression = refProp;
|
|
|
|
auto stat = Ptr(new WfVariableStatement);
|
|
stat->variable = varDesc;
|
|
block->statements.Add(stat);
|
|
}
|
|
|
|
for (vint i = 0; i < values.Count(); i++)
|
|
{
|
|
auto refCollection = Ptr(new WfReferenceExpression);
|
|
refCollection->name.value = L"<collection>";
|
|
|
|
auto refAdd = Ptr(new WfMemberExpression);
|
|
refAdd->parent = refCollection;
|
|
refAdd->name.value = L"Add";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAdd;
|
|
call->arguments.Add(values[i].expression);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case GuiInstancePropertyInfo::SupportArray:
|
|
{
|
|
auto refArray = Ptr(new WfConstructorExpression);
|
|
for (auto item : arguments.GetByIndex(index))
|
|
{
|
|
auto argument = Ptr(new WfConstructorArgument);
|
|
argument->key = item.expression;
|
|
refArray->arguments.Add(argument);
|
|
}
|
|
|
|
auto refValue = Ptr(new WfReferenceExpression);
|
|
refValue->name.value = variableName.ToString();
|
|
|
|
auto refProp = Ptr(new WfMemberExpression);
|
|
refProp->parent = refValue;
|
|
refProp->name.value = prop.ToString();
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refProp;
|
|
assign->second = refArray;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
block->statements.Add(stat);
|
|
}
|
|
break;
|
|
case GuiInstancePropertyInfo::SupportAssign:
|
|
{
|
|
auto& propertyValue = arguments.GetByIndex(index)[0];
|
|
if (propertyValue.expression)
|
|
{
|
|
auto refValue = Ptr(new WfReferenceExpression);
|
|
refValue->name.value = variableName.ToString();
|
|
|
|
auto refProp = Ptr(new WfMemberExpression);
|
|
refProp->parent = refValue;
|
|
refProp->name.value = prop.ToString();
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refProp;
|
|
assign->second = propertyValue.expression;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, attPosition,
|
|
L"Precompile: Property \"" +
|
|
prop.ToString() +
|
|
L"\" of type \"" +
|
|
typeInfo.typeName.ToString() +
|
|
L"\" is not assignable."));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> GetParameter(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const PropertyInfo& propertyInfo, GlobalStringKey variableName, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto refValue = Ptr(new WfReferenceExpression);
|
|
refValue->name.value = variableName.ToString();
|
|
|
|
auto refProp = Ptr(new WfMemberExpression);
|
|
refProp->parent = refValue;
|
|
refProp->name.value = propertyInfo.propertyName.ToString();
|
|
|
|
return refProp;
|
|
}
|
|
};
|
|
#undef CTOR_PARAM_NAME
|
|
#undef CTOR_PARAM_PREFIX
|
|
|
|
/***********************************************************************
|
|
GuiInstanceLoaderManager
|
|
***********************************************************************/
|
|
|
|
IGuiInstanceLoaderManager* instanceLoaderManager = 0;
|
|
|
|
IGuiInstanceLoaderManager* GetInstanceLoaderManager()
|
|
{
|
|
return instanceLoaderManager;
|
|
}
|
|
|
|
class GuiInstanceLoaderManager : public Object, public IGuiInstanceLoaderManager, public IGuiPlugin
|
|
{
|
|
protected:
|
|
typedef Dictionary<GlobalStringKey, Ptr<IGuiInstanceBinder>> BinderMap;
|
|
typedef Dictionary<GlobalStringKey, Ptr<IGuiInstanceEventBinder>> EventBinderMap;
|
|
typedef List<Ptr<IGuiInstanceDeserializer>> DeserializerList;
|
|
|
|
struct VirtualTypeInfo
|
|
{
|
|
GlobalStringKey typeName;
|
|
ITypeDescriptor* typeDescriptor = nullptr;
|
|
GlobalStringKey parentTypeName; // for virtual type only
|
|
Ptr<IGuiInstanceLoader> loader;
|
|
|
|
List<ITypeDescriptor*> parentTypes; // all direct or indirect base types that does not has a type info
|
|
List<VirtualTypeInfo*> parentTypeInfos; // type infos for all registered direct or indirect base types
|
|
};
|
|
|
|
typedef Dictionary<GlobalStringKey, Ptr<VirtualTypeInfo>> VirtualTypeInfoMap;
|
|
|
|
Ptr<IGuiInstanceLoader> rootLoader;
|
|
BinderMap binders;
|
|
EventBinderMap eventBinders;
|
|
DeserializerList deserializers;
|
|
VirtualTypeInfoMap typeInfos;
|
|
|
|
bool IsTypeExists(GlobalStringKey name)
|
|
{
|
|
return GetGlobalTypeManager()->GetTypeDescriptor(name.ToString()) != 0 || typeInfos.Keys().Contains(name);
|
|
}
|
|
|
|
void FindParentTypeInfos(Ptr<VirtualTypeInfo> 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<VirtualTypeInfo> 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();
|
|
}
|
|
}
|
|
public:
|
|
GuiInstanceLoaderManager()
|
|
{
|
|
rootLoader = Ptr(new GuiDefaultInstanceLoader);
|
|
}
|
|
|
|
GUI_PLUGIN_NAME(GacUI_Instance)
|
|
{
|
|
GUI_PLUGIN_DEPEND(GacUI_Parser);
|
|
}
|
|
|
|
void Load()override
|
|
{
|
|
instanceLoaderManager = this;
|
|
IGuiParserManager* manager = GetParserManager();
|
|
manager->SetParser(L"INSTANCE-ELEMENT-NAME", Ptr(new GuiInstanceContextElementNameParser));
|
|
}
|
|
|
|
void Unload()override
|
|
{
|
|
instanceLoaderManager = nullptr;
|
|
}
|
|
|
|
bool AddInstanceBinder(Ptr<IGuiInstanceBinder> 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 ? nullptr : binders.Values()[index].Obj();
|
|
}
|
|
|
|
bool AddInstanceEventBinder(Ptr<IGuiInstanceEventBinder> 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 ? nullptr : eventBinders.Values()[index].Obj();
|
|
}
|
|
|
|
bool AddInstanceDeserializer(Ptr<IGuiInstanceDeserializer> deserializer)override
|
|
{
|
|
if (deserializers.Contains(deserializer.Obj())) return false;
|
|
deserializers.Add(deserializer);
|
|
return true;
|
|
}
|
|
|
|
IGuiInstanceDeserializer* GetInstanceDeserializer(const IGuiInstanceLoader::PropertyInfo& propertyInfo, description::ITypeInfo* typeInfo)override
|
|
{
|
|
for (auto deserializer : deserializers)
|
|
{
|
|
if (deserializer->CanDeserialize(propertyInfo, typeInfo))
|
|
{
|
|
return deserializer.Obj();
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool CreateVirtualType(GlobalStringKey parentType, Ptr<IGuiInstanceLoader> loader)override
|
|
{
|
|
if (IsTypeExists(loader->GetTypeName()) || !IsTypeExists(parentType)) return false;
|
|
|
|
auto typeInfo = Ptr(new VirtualTypeInfo);
|
|
typeInfo->typeName = loader->GetTypeName();
|
|
typeInfo->parentTypeName = parentType;
|
|
typeInfo->loader = loader;
|
|
typeInfos.Add(loader->GetTypeName(), typeInfo);
|
|
FillParentTypeInfos(typeInfo);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SetLoader(Ptr<IGuiInstanceLoader> 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;
|
|
|
|
auto typeInfo = Ptr(new VirtualTypeInfo);
|
|
typeInfo->typeName = loader->GetTypeName();
|
|
typeInfo->typeDescriptor = typeDescriptor;
|
|
typeInfo->loader = loader;
|
|
typeInfos.Add(typeInfo->typeName, typeInfo);
|
|
FillParentTypeInfos(typeInfo);
|
|
|
|
for (auto 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<VirtualTypeInfo> typeInfo = typeInfos.Values()[index];
|
|
if (typeInfo->parentTypeInfos.Count() > 0)
|
|
{
|
|
return typeInfo->parentTypeInfos[0]->loader.Obj();
|
|
}
|
|
return rootLoader.Obj();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Ptr<description::ITypeInfo> GetTypeInfoForType(GlobalStringKey typeName)override
|
|
{
|
|
vint index = typeInfos.Keys().IndexOf(typeName);
|
|
auto td = index == -1
|
|
? GetGlobalTypeManager()->GetTypeDescriptor(typeName.ToString())
|
|
: typeInfos.Values()[index]->typeDescriptor;
|
|
if (!td) return nullptr;
|
|
|
|
if (auto ctor = td->GetConstructorGroup())
|
|
{
|
|
return CopyTypeInfo(ctor->GetMethod(0)->GetReturn());
|
|
}
|
|
else
|
|
{
|
|
return Ptr(new RawPtrTypeInfo(Ptr(new TypeDescriptorTypeInfo(td, TypeInfoHint::Normal))));
|
|
}
|
|
}
|
|
|
|
void GetVirtualTypes(collections::List<GlobalStringKey>& 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;
|
|
}
|
|
|
|
void ClearReflectionCache()override
|
|
{
|
|
rootLoader->ClearReflectionCache();
|
|
for (auto info : typeInfos.Values())
|
|
{
|
|
info->loader->ClearReflectionCache();
|
|
}
|
|
}
|
|
};
|
|
GUI_REGISTER_PLUGIN(GuiInstanceLoaderManager)
|
|
|
|
/***********************************************************************
|
|
Helper Functions
|
|
***********************************************************************/
|
|
|
|
void Split(const WString& input, const WString& delimiter, collections::List<WString>& fragments)
|
|
{
|
|
const wchar_t* attValue = input.Buffer();
|
|
while (*attValue)
|
|
{
|
|
// split the value by ';'
|
|
const wchar_t* attSemicolon = wcsstr(attValue, delimiter.Buffer());
|
|
WString pattern;
|
|
if (attSemicolon)
|
|
{
|
|
pattern = WString::CopyFrom(attValue, vint(attSemicolon - attValue));
|
|
attValue = attSemicolon + delimiter.Length();
|
|
}
|
|
else
|
|
{
|
|
vint len = wcslen(attValue);
|
|
pattern = WString::CopyFrom(attValue, len);
|
|
attValue += len;
|
|
}
|
|
|
|
fragments.Add(pattern);
|
|
}
|
|
}
|
|
|
|
void SplitTypeName(const WString& input, collections::List<WString>& fragments)
|
|
{
|
|
Split(input, L"::", fragments);
|
|
}
|
|
|
|
void SplitBySemicolon(const WString& input, collections::List<WString>& fragments)
|
|
{
|
|
Split(input, L";", fragments);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\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 instancequery;
|
|
using namespace controls;
|
|
using namespace stream;
|
|
|
|
/***********************************************************************
|
|
GuiResourceInstanceBinder (uri)
|
|
***********************************************************************/
|
|
|
|
class GuiResourceInstanceBinder : public Object, public IGuiInstanceBinder
|
|
{
|
|
public:
|
|
GlobalStringKey GetBindingName()override
|
|
{
|
|
return GlobalStringKey::_Uri;
|
|
}
|
|
|
|
bool ApplicableToConstructorArgument()override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool RequirePropertyExist()override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> GenerateConstructorArgument(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
WString protocol, path;
|
|
if (!IsResourceUrl(code, protocol, path))
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, position, L"Precompile: \"" + code + L"\" is not a valid resource uri."));
|
|
return nullptr;
|
|
}
|
|
else if (!precompileContext.resolver->ResolveResource(protocol, path))
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, position, L"Precompile: Resource \"" + code + L"\" does not exist."));
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
return Workflow_GetUriProperty(precompileContext, resolvingResult, loader, prop, propInfo, protocol, path, position, errors);
|
|
}
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> GenerateInstallStatement(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
WString protocol, path;
|
|
if (!IsResourceUrl(code, protocol, path))
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, position, L"Precompile: \"" + code + L"\" is not a valid resource uri."));
|
|
return nullptr;
|
|
}
|
|
else if (!precompileContext.resolver->ResolveResource(protocol, path))
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, position, L"Precompile: Resource \"" + code + L"\" does not exist."));
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
return Workflow_InstallUriProperty(precompileContext, resolvingResult, variableName, loader, prop, propInfo, protocol, path, position, errors);
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiReferenceInstanceBinder (ref)
|
|
***********************************************************************/
|
|
|
|
class GuiReferenceInstanceBinder : public Object, public IGuiInstanceBinder
|
|
{
|
|
public:
|
|
GlobalStringKey GetBindingName()override
|
|
{
|
|
return GlobalStringKey::_Ref;
|
|
}
|
|
|
|
bool ApplicableToConstructorArgument()override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool RequirePropertyExist()override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> GenerateConstructorArgument(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
CHECK_FAIL(L"GuiReferenceInstanceBinder::GenerateConstructorArgument()#This binder does not support binding to constructor arguments. Please call ApplicableToConstructorArgument() to determine before calling this function.");
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> GenerateInstallStatement(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
auto expression = Ptr(new WfReferenceExpression);
|
|
expression->name.value = code;
|
|
return Workflow_InstallEvalProperty(precompileContext, resolvingResult, variableName, loader, prop, propInfo, expression, position, errors);
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiEvalInstanceBinder (eval)
|
|
***********************************************************************/
|
|
|
|
class GuiEvalInstanceBinder : public Object, public IGuiInstanceBinder
|
|
{
|
|
public:
|
|
GlobalStringKey GetBindingName()override
|
|
{
|
|
return GlobalStringKey::_Eval;
|
|
}
|
|
|
|
bool ApplicableToConstructorArgument()override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool RequirePropertyExist()override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> GenerateConstructorArgument(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
return Workflow_ParseExpression(precompileContext, { resolvingResult.resource }, code, position, errors);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> GenerateInstallStatement(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
if(auto expression = Workflow_ParseExpression(precompileContext, { resolvingResult.resource }, code, position, errors))
|
|
{
|
|
return Workflow_InstallEvalProperty(precompileContext, resolvingResult, variableName, loader, prop, propInfo, expression, position, errors);
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiBindInstanceBinder (bind)
|
|
***********************************************************************/
|
|
|
|
class GuiBindInstanceBinder : public Object, public IGuiInstanceBinder
|
|
{
|
|
public:
|
|
GlobalStringKey GetBindingName()override
|
|
{
|
|
return GlobalStringKey::_Bind;
|
|
}
|
|
|
|
bool ApplicableToConstructorArgument()override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool RequirePropertyExist()override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> GenerateConstructorArgument(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
CHECK_FAIL(L"GuiBindInstanceBinder::GenerateConstructorArgument()#This binder does not support binding to constructor arguments. Please call ApplicableToConstructorArgument() to determine before calling this function.");
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> GenerateInstallStatement(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
if(auto expression = Workflow_ParseExpression(precompileContext, { resolvingResult.resource }, code, position, errors))
|
|
{
|
|
auto inferExpr = Ptr(new WfInferExpression);
|
|
inferExpr->expression = expression;
|
|
inferExpr->type = GetTypeFromTypeInfo(propertyInfo->GetReturn());
|
|
|
|
auto bindExpr = Ptr(new WfBindExpression);
|
|
bindExpr->expression = inferExpr;
|
|
|
|
return Workflow_InstallBindProperty(precompileContext, resolvingResult, variableName, propertyInfo, bindExpr);
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiFormatInstanceBinder (format)
|
|
***********************************************************************/
|
|
|
|
class GuiFormatInstanceBinder : public Object, public IGuiInstanceBinder
|
|
{
|
|
public:
|
|
GlobalStringKey GetBindingName()override
|
|
{
|
|
return GlobalStringKey::_Format;
|
|
}
|
|
|
|
bool ApplicableToConstructorArgument()override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool RequirePropertyExist()override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> GenerateConstructorArgument(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
CHECK_FAIL(L"GuiFormatInstanceBinder::GenerateConstructorArgument()#This binder does not support binding to constructor arguments. Please call ApplicableToConstructorArgument() to determine before calling this function.");
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> GenerateInstallStatement(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
if (auto expression = Workflow_ParseExpression(precompileContext, { resolvingResult.resource }, L"bind($\"" + code + L"\")", position, errors, { 0,7 })) // bind($"
|
|
{
|
|
return Workflow_InstallBindProperty(precompileContext, resolvingResult, variableName, propertyInfo, expression);
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiLocalizedStringInstanceBinder (str)
|
|
***********************************************************************/
|
|
|
|
class GuiLocalizedStringInstanceBinder : public Object, public IGuiInstanceBinder
|
|
{
|
|
public:
|
|
GlobalStringKey GetBindingName()override
|
|
{
|
|
return GlobalStringKey::_Str;
|
|
}
|
|
|
|
bool ApplicableToConstructorArgument()override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool RequirePropertyExist()override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> GenerateConstructorArgument(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
CHECK_FAIL(L"GuiLocalizedStringInstanceBinder::GenerateConstructorArgument()#This binder does not support binding to constructor arguments. Please call ApplicableToConstructorArgument() to determine before calling this function.");
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> GenerateInstallStatement(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
if (auto expression = Workflow_ParseExpression(precompileContext, { resolvingResult.resource }, code, position, errors, { 0,0 }))
|
|
{
|
|
vint errorCount = errors.Count();
|
|
if (auto callExpr = expression.Cast<WfCallExpression>())
|
|
{
|
|
if (auto refExpr = callExpr->function.Cast<WfReferenceExpression>())
|
|
{
|
|
auto defaultLs=From(resolvingResult.context->localizeds)
|
|
.Where([](Ptr<GuiInstanceLocalized> ls)
|
|
{
|
|
return ls->defaultStrings;
|
|
})
|
|
.First(nullptr);
|
|
|
|
if (defaultLs)
|
|
{
|
|
auto thisExpr = Ptr(new WfReferenceExpression);
|
|
thisExpr->name.value = L"<this>";
|
|
thisExpr->codeRange = refExpr->codeRange;
|
|
|
|
auto thisMember = Ptr(new WfMemberExpression);
|
|
thisMember->parent = thisExpr;
|
|
thisMember->name.value = defaultLs->name.ToString();
|
|
thisMember->codeRange = refExpr->codeRange;
|
|
|
|
auto refMember = Ptr(new WfMemberExpression);
|
|
refMember->parent = thisMember;
|
|
refMember->name.value = refExpr->name.value;
|
|
refMember->codeRange = refExpr->codeRange;
|
|
|
|
callExpr->function = refMember;
|
|
goto PASSED;
|
|
}
|
|
else
|
|
{
|
|
errors.Add({ position,L"Precompiled: Omitting the name of the localized strings requires specifying a default one in <ref.LocalizedStrings> by adding a Default=\"true\" attribute." });
|
|
}
|
|
}
|
|
else if (auto memberExpr = callExpr->function.Cast<WfMemberExpression>())
|
|
{
|
|
if (auto refStrings = memberExpr->parent.Cast<WfReferenceExpression>())
|
|
{
|
|
auto thisExpr = Ptr(new WfReferenceExpression);
|
|
thisExpr->name.value = L"<this>";
|
|
thisExpr->codeRange = refStrings->codeRange;
|
|
|
|
auto thisMember = Ptr(new WfMemberExpression);
|
|
thisMember->parent = thisExpr;
|
|
thisMember->name.value = refStrings->name.value;
|
|
thisMember->codeRange = refStrings->codeRange;
|
|
|
|
memberExpr->parent = thisMember;
|
|
goto PASSED;
|
|
}
|
|
}
|
|
|
|
errors.Add({ position,L"Precompiled: The function expression in binding \"-str\" should be a \"<string-name>\" or \"<localized-strings-name>.<string-name>\"." });
|
|
PASSED:;
|
|
}
|
|
else
|
|
{
|
|
errors.Add({ position,L"Precompiled: Expression in binding \"-str\" should be a function call expression." });
|
|
}
|
|
|
|
if (errorCount == errors.Count())
|
|
{
|
|
auto bindExpr = Ptr(new WfBindExpression);
|
|
bindExpr->expression = expression;
|
|
bindExpr->codeRange = expression->codeRange;
|
|
|
|
return Workflow_InstallBindProperty(precompileContext, resolvingResult, variableName, propertyInfo, bindExpr);
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiEvalInstanceEventBinder (eval)
|
|
***********************************************************************/
|
|
|
|
class GuiEvalInstanceEventBinder : public Object, public IGuiInstanceEventBinder
|
|
{
|
|
public:
|
|
GlobalStringKey GetBindingName()override
|
|
{
|
|
return GlobalStringKey::_Eval;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> GenerateInstallStatement(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IEventInfo* eventInfo, const WString& code, GuiResourceTextPos position, GuiResourceError::List& errors)override
|
|
{
|
|
bool coroutine = false;
|
|
{
|
|
auto reading = code.Buffer();
|
|
while (true)
|
|
{
|
|
switch (*reading)
|
|
{
|
|
case ' ':
|
|
case '\t':
|
|
case '\r':
|
|
case '\n':
|
|
reading++;
|
|
break;
|
|
default:
|
|
goto BEGIN_TESTING;
|
|
}
|
|
}
|
|
BEGIN_TESTING:
|
|
coroutine = *reading == '$';
|
|
}
|
|
|
|
auto parseFunction = coroutine ? &Workflow_ParseCoProviderStatement : &Workflow_ParseStatement;
|
|
if (auto statement = parseFunction(precompileContext, { resolvingResult.resource }, code, position, errors, { 0,0 }))
|
|
{
|
|
return Workflow_InstallEvalEvent(precompileContext, resolvingResult, variableName, eventInfo, statement);
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiPredefinedInstanceBindersPlugin
|
|
***********************************************************************/
|
|
|
|
class GuiParser_WorkflowType : public IGuiParser<WfType>
|
|
{
|
|
protected:
|
|
Ptr<workflow::Parser> parser;
|
|
|
|
public:
|
|
GuiParser_WorkflowType(Ptr<workflow::Parser> _parser)
|
|
:parser(_parser)
|
|
{
|
|
}
|
|
|
|
Ptr<WfType> ParseInternal(const WString& text, List<glr::ParsingError>& errors) override
|
|
{
|
|
auto handler = glr::InstallDefaultErrorMessageGenerator(*parser.Obj(), errors);
|
|
auto ast = ParseType(text, *parser.Obj());
|
|
parser->OnError.Remove(handler);
|
|
return ast;
|
|
}
|
|
};
|
|
|
|
class GuiParser_WorkflowExpression : public IGuiParser<WfExpression>
|
|
{
|
|
protected:
|
|
Ptr<workflow::Parser> parser;
|
|
|
|
public:
|
|
GuiParser_WorkflowExpression(Ptr<workflow::Parser> _parser)
|
|
:parser(_parser)
|
|
{
|
|
}
|
|
|
|
Ptr<WfExpression> ParseInternal(const WString& text, List<glr::ParsingError>& errors) override
|
|
{
|
|
auto handler = glr::InstallDefaultErrorMessageGenerator(*parser.Obj(), errors);
|
|
auto ast = ParseExpression(text, *parser.Obj());
|
|
parser->OnError.Remove(handler);
|
|
return ast;
|
|
}
|
|
};
|
|
|
|
class GuiParser_WorkflowStatement : public IGuiParser<WfStatement>
|
|
{
|
|
protected:
|
|
Ptr<workflow::Parser> parser;
|
|
|
|
public:
|
|
GuiParser_WorkflowStatement(Ptr<workflow::Parser> _parser)
|
|
:parser(_parser)
|
|
{
|
|
}
|
|
|
|
Ptr<WfStatement> ParseInternal(const WString& text, List<glr::ParsingError>& errors) override
|
|
{
|
|
auto handler = glr::InstallDefaultErrorMessageGenerator(*parser.Obj(), errors);
|
|
auto ast = ParseStatement(text, *parser.Obj());
|
|
parser->OnError.Remove(handler);
|
|
return ast;
|
|
}
|
|
};
|
|
|
|
class GuiParser_WorkflowCoProviderStatement : public IGuiParser<WfStatement>
|
|
{
|
|
protected:
|
|
Ptr<workflow::Parser> parser;
|
|
|
|
public:
|
|
GuiParser_WorkflowCoProviderStatement(Ptr<workflow::Parser> _parser)
|
|
:parser(_parser)
|
|
{
|
|
}
|
|
|
|
Ptr<WfStatement> ParseInternal(const WString& text, List<glr::ParsingError>& errors) override
|
|
{
|
|
auto handler = glr::InstallDefaultErrorMessageGenerator(*parser.Obj(), errors);
|
|
auto ast = ParseCoProviderStatement(text, *parser.Obj());
|
|
parser->OnError.Remove(handler);
|
|
return ast;
|
|
}
|
|
};
|
|
|
|
class GuiParser_WorkflowDeclaration : public IGuiParser<WfDeclaration>
|
|
{
|
|
protected:
|
|
Ptr<workflow::Parser> parser;
|
|
|
|
public:
|
|
GuiParser_WorkflowDeclaration(Ptr<workflow::Parser> _parser)
|
|
:parser(_parser)
|
|
{
|
|
}
|
|
|
|
Ptr<WfDeclaration> ParseInternal(const WString& text, List<glr::ParsingError>& errors) override
|
|
{
|
|
auto handler = glr::InstallDefaultErrorMessageGenerator(*parser.Obj(), errors);
|
|
auto ast = ParseDeclaration(text, *parser.Obj());
|
|
parser->OnError.Remove(handler);
|
|
return ast;
|
|
}
|
|
};
|
|
|
|
class GuiParser_WorkflowModule : public IGuiParser<WfModule>
|
|
{
|
|
protected:
|
|
Ptr<workflow::Parser> parser;
|
|
|
|
public:
|
|
GuiParser_WorkflowModule(Ptr<workflow::Parser> _parser)
|
|
:parser(_parser)
|
|
{
|
|
}
|
|
|
|
Ptr<WfModule> ParseInternal(const WString& text, List<glr::ParsingError>& errors) override
|
|
{
|
|
auto handler = glr::InstallDefaultErrorMessageGenerator(*parser.Obj(), errors);
|
|
auto ast = ParseModule(text, *parser.Obj());
|
|
parser->OnError.Remove(handler);
|
|
return ast;
|
|
}
|
|
};
|
|
|
|
class GuiParser_InstanceQuery : public IGuiParser<GuiIqQuery>
|
|
{
|
|
protected:
|
|
instancequery::Parser parser;
|
|
|
|
public:
|
|
Ptr<GuiIqQuery> ParseInternal(const WString& text, List<glr::ParsingError>& errors) override
|
|
{
|
|
auto handler = glr::InstallDefaultErrorMessageGenerator(parser, errors);
|
|
auto ast = parser.ParseQueryRoot(text);
|
|
parser.OnError.Remove(handler);
|
|
return ast;
|
|
}
|
|
};
|
|
|
|
class GuiPredefinedInstanceBindersPlugin : public Object, public IGuiPlugin
|
|
{
|
|
public:
|
|
|
|
GUI_PLUGIN_NAME(GacUI_Compiler_ParsersAndBinders)
|
|
{
|
|
GUI_PLUGIN_DEPEND(GacUI_Parser);
|
|
GUI_PLUGIN_DEPEND(GacUI_Res_ResourceResolver);
|
|
GUI_PLUGIN_DEPEND(GacUI_Instance);
|
|
GUI_PLUGIN_DEPEND(GacUI_Instance_Reflection);
|
|
}
|
|
|
|
void Load()override
|
|
{
|
|
WorkflowAstLoadTypes();
|
|
GuiInstanceQueryAstLoadTypes();
|
|
{
|
|
auto workflowParser = Ptr(new workflow::Parser);
|
|
|
|
IGuiParserManager* manager = GetParserManager();
|
|
manager->SetParser(L"WORKFLOW-TYPE", Ptr(new GuiParser_WorkflowType(workflowParser)));
|
|
manager->SetParser(L"WORKFLOW-EXPRESSION", Ptr(new GuiParser_WorkflowExpression(workflowParser)));
|
|
manager->SetParser(L"WORKFLOW-STATEMENT", Ptr(new GuiParser_WorkflowStatement(workflowParser)));
|
|
manager->SetParser(L"WORKFLOW-COPROVIDER-STATEMENT", Ptr(new GuiParser_WorkflowCoProviderStatement(workflowParser)));
|
|
manager->SetParser(L"WORKFLOW-DECLARATION", Ptr(new GuiParser_WorkflowDeclaration(workflowParser)));
|
|
manager->SetParser(L"WORKFLOW-MODULE", Ptr(new GuiParser_WorkflowModule(workflowParser)));
|
|
manager->SetParser(L"INSTANCE-QUERY", Ptr(new GuiParser_InstanceQuery));
|
|
}
|
|
{
|
|
IGuiInstanceLoaderManager* manager=GetInstanceLoaderManager();
|
|
|
|
manager->AddInstanceBinder(Ptr(new GuiResourceInstanceBinder));
|
|
manager->AddInstanceBinder(Ptr(new GuiReferenceInstanceBinder));
|
|
manager->AddInstanceBinder(Ptr(new GuiEvalInstanceBinder));
|
|
manager->AddInstanceBinder(Ptr(new GuiBindInstanceBinder));
|
|
manager->AddInstanceBinder(Ptr(new GuiFormatInstanceBinder));
|
|
manager->AddInstanceBinder(Ptr(new GuiLocalizedStringInstanceBinder));
|
|
manager->AddInstanceEventBinder(Ptr(new GuiEvalInstanceEventBinder));
|
|
}
|
|
}
|
|
|
|
void Unload()override
|
|
{
|
|
}
|
|
};
|
|
GUI_REGISTER_PLUGIN(GuiPredefinedInstanceBindersPlugin)
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\GUIINSTANCELOADER_PREDEFINEDINSTANCEDESERIALIZERS.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace collections;
|
|
using namespace reflection::description;
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
using namespace controls;
|
|
using namespace controls::list;
|
|
using namespace templates;
|
|
|
|
/***********************************************************************
|
|
GuiTemplatePropertyDeserializer
|
|
***********************************************************************/
|
|
|
|
class GuiTemplatePropertyDeserializer : public Object, public IGuiInstanceDeserializer
|
|
{
|
|
protected:
|
|
Ptr<ITypeInfo> stringType;
|
|
|
|
bool IsTemplatePropertyType(ITypeInfo* propType)
|
|
{
|
|
if (propType->GetDecorator() == ITypeInfo::SharedPtr)
|
|
{
|
|
auto genericType = propType->GetElementType();
|
|
if (genericType->GetDecorator() == ITypeInfo::Generic && genericType->GetGenericArgumentCount() == 2)
|
|
{
|
|
if (genericType->GetElementType()->GetTypeDescriptor() == description::GetTypeDescriptor<IValueFunctionProxy>())
|
|
{
|
|
if (genericType->GetGenericArgument(1)->GetTypeDescriptor() == description::GetTypeDescriptor<Value>())
|
|
{
|
|
auto returnType = genericType->GetGenericArgument(0);
|
|
if (returnType->GetDecorator() == ITypeInfo::RawPtr)
|
|
{
|
|
if (returnType->GetElementType()->GetTypeDescriptor()->CanConvertTo(description::GetTypeDescriptor<GuiTemplate>()))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool IsDataVisualizerFactoryType(ITypeInfo* propType)
|
|
{
|
|
return propType->GetDecorator() == ITypeInfo::SharedPtr && propType->GetTypeDescriptor() == description::GetTypeDescriptor<list::IDataVisualizerFactory>();
|
|
}
|
|
|
|
bool IsDataEditorFactoryType(ITypeInfo* propType)
|
|
{
|
|
return propType->GetDecorator() == ITypeInfo::SharedPtr && propType->GetTypeDescriptor() == description::GetTypeDescriptor<list::IDataEditorFactory>();
|
|
}
|
|
|
|
public:
|
|
GuiTemplatePropertyDeserializer()
|
|
{
|
|
stringType = TypeInfoRetriver<WString>::CreateTypeInfo();
|
|
}
|
|
|
|
bool CanDeserialize(const IGuiInstanceLoader::PropertyInfo& propertyInfo, description::ITypeInfo* typeInfo)override
|
|
{
|
|
return IsTemplatePropertyType(typeInfo) || IsDataVisualizerFactoryType(typeInfo) || IsDataEditorFactoryType(typeInfo);
|
|
}
|
|
|
|
description::ITypeInfo* DeserializeAs(const IGuiInstanceLoader::PropertyInfo& propertyInfo, description::ITypeInfo* typeInfo)override
|
|
{
|
|
return stringType.Obj();
|
|
}
|
|
|
|
static void GetItemTemplateType(
|
|
types::ResolvingResult& resolvingResult,
|
|
WString typeNamesString,
|
|
List<ITypeDescriptor*>& tds,
|
|
GuiResourceTextPos tagPosition,
|
|
GuiResourceError::List& errors
|
|
)
|
|
{
|
|
List<WString> typeNames;
|
|
SplitBySemicolon(typeNamesString, typeNames);
|
|
if (typeNames.Count() == 0)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, tagPosition,
|
|
L"Precompile: Template list \"" +
|
|
typeNamesString +
|
|
L"\" cannot be empty."));
|
|
}
|
|
|
|
for (auto controlTemplateName : typeNames)
|
|
{
|
|
auto controlTemplateTd = description::GetTypeDescriptor(controlTemplateName);
|
|
if (!controlTemplateTd)
|
|
{
|
|
auto index = INVLOC.FindFirst(controlTemplateName, L":", Locale::None);
|
|
GlobalStringKey namespaceName;
|
|
auto typeName = controlTemplateName;
|
|
if (index.key != -1)
|
|
{
|
|
namespaceName = GlobalStringKey::Get(controlTemplateName.Left(index.key));
|
|
typeName = controlTemplateName.Right(controlTemplateName.Length() - index.key - index.value);
|
|
}
|
|
|
|
auto source = FindInstanceLoadingSource(resolvingResult.context, namespaceName, typeName);
|
|
if (auto typeInfo = GetInstanceLoaderManager()->GetTypeInfoForType(source.typeName))
|
|
{
|
|
controlTemplateTd = typeInfo->GetTypeDescriptor();
|
|
}
|
|
}
|
|
if (controlTemplateTd)
|
|
{
|
|
tds.Add(controlTemplateTd);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, tagPosition,
|
|
L"Precompile: Type \"" +
|
|
controlTemplateName +
|
|
L"\" does not exist."));
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
static Ptr<WfExpression> CreateTemplateFactory(
|
|
types::ResolvingResult& resolvingResult,
|
|
List<ITypeDescriptor*>& controlTemplateTds,
|
|
ITypeInfo* returnTemplateType,
|
|
ITypeInfo* expectedTemplateType,
|
|
GuiResourceTextPos tagPosition,
|
|
GuiResourceError::List& errors
|
|
)
|
|
{
|
|
auto funcCreateTemplate = Ptr(new WfFunctionDeclaration);
|
|
funcCreateTemplate->functionKind = WfFunctionKind::Normal;
|
|
funcCreateTemplate->anonymity = WfFunctionAnonymity::Anonymous;
|
|
funcCreateTemplate->returnType = GetTypeFromTypeInfo(returnTemplateType);
|
|
|
|
auto argViewModel = Ptr(new WfFunctionArgument);
|
|
argViewModel->type = GetTypeFromTypeInfo(TypeInfoRetriver<Value>::CreateTypeInfo().Obj());
|
|
argViewModel->name.value = L"<viewModel>";
|
|
funcCreateTemplate->arguments.Add(argViewModel);
|
|
|
|
auto block = Ptr(new WfBlockStatement);
|
|
funcCreateTemplate->statement = block;
|
|
|
|
ITypeDescriptor* stopControlTemplateTd = nullptr;
|
|
for (auto controlTemplateTd : controlTemplateTds)
|
|
{
|
|
if (!controlTemplateTd->CanConvertTo(expectedTemplateType->GetTypeDescriptor()))
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, tagPosition,
|
|
L"Precompile: Type \"" +
|
|
controlTemplateTd->GetTypeName() +
|
|
L"\" cannot be used here because it requires \"" +
|
|
expectedTemplateType->GetTypeDescriptor()->GetTypeName() +
|
|
L"\" or its derived classes."));
|
|
}
|
|
|
|
if (stopControlTemplateTd)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, tagPosition,
|
|
L"Precompile: Type \"" +
|
|
controlTemplateTd->GetTypeName() +
|
|
L"\" will never be tried, because \"" +
|
|
stopControlTemplateTd->GetTypeName() +
|
|
L"\", which is listed before, has a default constructor. So whatever the view model is, it will be the last choice."));
|
|
continue;
|
|
}
|
|
|
|
ITypeInfo* viewModelType = nullptr;
|
|
{
|
|
auto ctors = controlTemplateTd->GetConstructorGroup();
|
|
if (!ctors || ctors->GetMethodCount() != 1)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, tagPosition,
|
|
L"Precompile: To use type \"" +
|
|
controlTemplateTd->GetTypeName() +
|
|
L"\" as a control template or item template, it should have exactly one constructor."));
|
|
continue;
|
|
}
|
|
|
|
auto ctor = ctors->GetMethod(0);
|
|
if (ctor->GetParameterCount() > 1)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, tagPosition,
|
|
L"Precompile: To use type \"" +
|
|
controlTemplateTd->GetTypeName() +
|
|
L"\" as a control template or item template, its constructor cannot have more than one parameter."));
|
|
continue;
|
|
}
|
|
|
|
if (ctor->GetParameterCount() != 0)
|
|
{
|
|
viewModelType = ctor->GetParameter(0)->GetType();
|
|
}
|
|
}
|
|
|
|
if (!viewModelType)
|
|
{
|
|
stopControlTemplateTd = controlTemplateTd;
|
|
}
|
|
|
|
auto subBlock = Ptr(new WfBlockStatement);
|
|
block->statements.Add(subBlock);
|
|
|
|
Ptr<ITypeInfo> controlTemplateType;
|
|
{
|
|
auto elementType = Ptr(new TypeDescriptorTypeInfo(controlTemplateTd, TypeInfoHint::Normal));
|
|
auto pointerType = Ptr(new RawPtrTypeInfo(elementType));
|
|
|
|
controlTemplateType = pointerType;
|
|
}
|
|
|
|
Ptr<WfBlockStatement> returnStatBlock;
|
|
if (viewModelType)
|
|
{
|
|
auto refViewModel = Ptr(new WfReferenceExpression);
|
|
refViewModel->name.value = L"<viewModel>";
|
|
|
|
auto condition = Ptr(new WfTypeTestingExpression);
|
|
condition->test = WfTypeTesting::IsType;
|
|
condition->expression = refViewModel;
|
|
condition->type = GetTypeFromTypeInfo(viewModelType);
|
|
|
|
auto ifStat = Ptr(new WfIfStatement);
|
|
subBlock->statements.Add(ifStat);
|
|
ifStat->expression = condition;
|
|
|
|
returnStatBlock = Ptr(new WfBlockStatement);
|
|
ifStat->trueBranch = returnStatBlock;
|
|
}
|
|
else
|
|
{
|
|
returnStatBlock = subBlock;
|
|
}
|
|
|
|
{
|
|
auto createControlTemplate = Ptr(new WfNewClassExpression);
|
|
createControlTemplate->type = GetTypeFromTypeInfo(controlTemplateType.Obj());
|
|
if (viewModelType)
|
|
{
|
|
auto refViewModel = Ptr(new WfReferenceExpression);
|
|
refViewModel->name.value = L"<viewModel>";
|
|
|
|
auto cast = Ptr(new WfTypeCastingExpression);
|
|
cast->strategy = WfTypeCastingStrategy::Strong;
|
|
cast->expression = refViewModel;
|
|
cast->type = GetTypeFromTypeInfo(viewModelType);
|
|
createControlTemplate->arguments.Add(cast);
|
|
}
|
|
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = createControlTemplate;
|
|
returnStatBlock->statements.Add(returnStat);
|
|
}
|
|
}
|
|
|
|
if (!stopControlTemplateTd)
|
|
{
|
|
auto value = Ptr(new WfStringExpression);
|
|
value->value.value = L"Cannot find a matched control template to create.";
|
|
|
|
auto raiseStat = Ptr(new WfRaiseExceptionStatement);
|
|
raiseStat->expression = value;
|
|
|
|
block->statements.Add(raiseStat);
|
|
}
|
|
|
|
auto expr = Ptr(new WfFunctionExpression);
|
|
expr->function = funcCreateTemplate;
|
|
return expr;
|
|
}
|
|
|
|
static Ptr<WfExpression> CreateDataVisualizerFactory(
|
|
types::ResolvingResult& resolvingResult,
|
|
List<ITypeDescriptor*>& controlTemplateTds,
|
|
GuiResourceTextPos tagPosition,
|
|
GuiResourceError::List& errors
|
|
)
|
|
{
|
|
auto templateType = TypeInfoRetriver<GuiGridVisualizerTemplate*>::CreateTypeInfo();
|
|
Ptr<WfExpression> previousFactory;
|
|
for (auto [controlTemplateTd, index] : indexed(controlTemplateTds))
|
|
{
|
|
List<ITypeDescriptor*> tds;
|
|
tds.Add(controlTemplateTd);
|
|
auto refFactory = CreateTemplateFactory(resolvingResult, tds, templateType.Obj(), templateType.Obj(), tagPosition, errors);
|
|
auto createStyle = Ptr(new WfNewClassExpression);
|
|
createStyle->type = GetTypeFromTypeInfo(TypeInfoRetriver<Ptr<list::DataVisualizerFactory>>::CreateTypeInfo().Obj());
|
|
createStyle->arguments.Add(refFactory);
|
|
|
|
if (index > 0)
|
|
{
|
|
createStyle->arguments.Add(previousFactory);
|
|
}
|
|
else
|
|
{
|
|
auto nullExpr = Ptr(new WfLiteralExpression);
|
|
nullExpr->value = WfLiteralValue::Null;
|
|
createStyle->arguments.Add(nullExpr);
|
|
}
|
|
previousFactory = createStyle;
|
|
}
|
|
return previousFactory;
|
|
}
|
|
|
|
static Ptr<WfExpression> CreateDataEditorFactory(
|
|
types::ResolvingResult& resolvingResult,
|
|
List<ITypeDescriptor*>& controlTemplateTds,
|
|
GuiResourceTextPos tagPosition,
|
|
GuiResourceError::List& errors
|
|
)
|
|
{
|
|
auto templateType = TypeInfoRetriver<GuiGridEditorTemplate*>::CreateTypeInfo();
|
|
auto refFactory = CreateTemplateFactory(resolvingResult, controlTemplateTds, templateType.Obj(), templateType.Obj(), tagPosition, errors);
|
|
auto createStyle = Ptr(new WfNewClassExpression);
|
|
createStyle->type = GetTypeFromTypeInfo(TypeInfoRetriver<Ptr<list::DataEditorFactory>>::CreateTypeInfo().Obj());
|
|
createStyle->arguments.Add(refFactory);
|
|
return createStyle;
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> Deserialize(
|
|
GuiResourcePrecompileContext& precompileContext,
|
|
types::ResolvingResult& resolvingResult,
|
|
const IGuiInstanceLoader::PropertyInfo& propertyInfo,
|
|
description::ITypeInfo* typeInfo,
|
|
Ptr<workflow::WfExpression> valueExpression,
|
|
GuiResourceTextPos tagPosition,
|
|
GuiResourceError::List& errors
|
|
)override
|
|
{
|
|
auto stringExpr = valueExpression.Cast<WfStringExpression>();
|
|
|
|
List<ITypeDescriptor*> tds;
|
|
GetItemTemplateType(resolvingResult, stringExpr->value.value, tds, tagPosition, errors);
|
|
|
|
if (IsDataVisualizerFactoryType(typeInfo))
|
|
{
|
|
return CreateDataVisualizerFactory(resolvingResult, tds, tagPosition, errors);
|
|
}
|
|
else if (IsDataEditorFactoryType(typeInfo))
|
|
{
|
|
return CreateDataEditorFactory(resolvingResult, tds, tagPosition, errors);
|
|
}
|
|
else
|
|
{
|
|
auto returnTemplateType = typeInfo->GetElementType()->GetGenericArgument(0);
|
|
auto expectedTemplateType = returnTemplateType;
|
|
if (propertyInfo.propertyName == GlobalStringKey::_ControlTemplate)
|
|
{
|
|
auto td = propertyInfo.typeInfo.typeInfo->GetTypeDescriptor();
|
|
if (td != nullptr && td->CanConvertTo(description::GetTypeDescriptor<GuiControl>()))
|
|
{
|
|
auto methodGroup = td->GetMethodGroupByName(L"GetControlTemplateObject", true);
|
|
vint count = methodGroup->GetMethodCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto methodInfo = methodGroup->GetMethod(i);
|
|
if (methodInfo->GetParameterCount() == 1)
|
|
{
|
|
auto returnType = methodInfo->GetReturn();
|
|
if (returnType->GetDecorator() == ITypeInfo::RawPtr)
|
|
{
|
|
if (returnType->GetTypeDescriptor()->CanConvertTo(description::GetTypeDescriptor<GuiControlTemplate>()))
|
|
{
|
|
expectedTemplateType = returnType;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return CreateTemplateFactory(resolvingResult, tds, returnTemplateType, expectedTemplateType, tagPosition, errors);
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiItemPropertyDeserializer
|
|
***********************************************************************/
|
|
|
|
class GuiItemPropertyDeserializer : public Object, public IGuiInstanceDeserializer
|
|
{
|
|
protected:
|
|
Ptr<ITypeInfo> stringType;
|
|
|
|
bool IsItemPropertyType(ITypeInfo* propType)
|
|
{
|
|
if (propType->GetDecorator() == ITypeInfo::SharedPtr)
|
|
{
|
|
auto genericType = propType->GetElementType();
|
|
if (genericType->GetDecorator() == ITypeInfo::Generic && genericType->GetGenericArgumentCount() == 2)
|
|
{
|
|
if (genericType->GetElementType()->GetTypeDescriptor() == description::GetTypeDescriptor<IValueFunctionProxy>())
|
|
{
|
|
if (genericType->GetGenericArgument(1)->GetTypeDescriptor() == description::GetTypeDescriptor<Value>())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool IsWritableItemPropertyType(ITypeInfo* propType)
|
|
{
|
|
if (propType->GetDecorator() == ITypeInfo::SharedPtr)
|
|
{
|
|
auto genericType = propType->GetElementType();
|
|
if (genericType->GetDecorator() == ITypeInfo::Generic && genericType->GetGenericArgumentCount() == 4)
|
|
{
|
|
if (genericType->GetElementType()->GetTypeDescriptor() == description::GetTypeDescriptor<IValueFunctionProxy>())
|
|
{
|
|
if (genericType->GetGenericArgument(1)->GetTypeDescriptor() == description::GetTypeDescriptor<Value>()
|
|
&& genericType->GetGenericArgument(3)->GetTypeDescriptor() == description::GetTypeDescriptor<bool>())
|
|
{
|
|
if (IsSameType(genericType->GetGenericArgument(0), genericType->GetGenericArgument(2)))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public:
|
|
GuiItemPropertyDeserializer()
|
|
{
|
|
stringType = TypeInfoRetriver<WString>::CreateTypeInfo();
|
|
}
|
|
|
|
bool CanDeserialize(const IGuiInstanceLoader::PropertyInfo& propertyInfo, description::ITypeInfo* typeInfo)override
|
|
{
|
|
return IsItemPropertyType(typeInfo) || IsWritableItemPropertyType(typeInfo);
|
|
}
|
|
|
|
description::ITypeInfo* DeserializeAs(const IGuiInstanceLoader::PropertyInfo& propertyInfo, description::ITypeInfo* typeInfo)override
|
|
{
|
|
return stringType.Obj();
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> Deserialize(
|
|
GuiResourcePrecompileContext& precompileContext,
|
|
types::ResolvingResult& resolvingResult,
|
|
const IGuiInstanceLoader::PropertyInfo& propertyInfo,
|
|
description::ITypeInfo* typeInfo,
|
|
Ptr<workflow::WfExpression> valueExpression,
|
|
GuiResourceTextPos tagPosition,
|
|
GuiResourceError::List& errors
|
|
)override
|
|
{
|
|
auto stringExpr = valueExpression.Cast<WfStringExpression>();
|
|
Ptr<WfExpression> propertyExpression;
|
|
{
|
|
propertyExpression = Workflow_ParseExpression(precompileContext, { resolvingResult.resource }, stringExpr->value.value, tagPosition, errors);
|
|
if (!propertyExpression)
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
vint indexItemType = resolvingResult.envVars.Keys().IndexOf(GlobalStringKey::Get(L"ItemType"));
|
|
if (indexItemType == -1)
|
|
{
|
|
auto error
|
|
= L"Precompile: env.ItemType must be specified before deserializing \""
|
|
+ stringExpr->value.value
|
|
+ L"\" to value of type \""
|
|
+ typeInfo->GetTypeFriendlyName()
|
|
+ L"\".";
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, tagPosition, error));
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<WfType> itemType;
|
|
{
|
|
const auto& values = resolvingResult.envVars.GetByIndex(indexItemType);
|
|
auto itemTypeValue = values[values.Count() - 1];
|
|
|
|
itemType = Workflow_ParseType(precompileContext, { resolvingResult.resource }, itemTypeValue->value, itemTypeValue->valuePosition, errors);
|
|
if (!itemType)
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
vint indexItemName = resolvingResult.envVars.Keys().IndexOf(GlobalStringKey::Get(L"ItemName"));
|
|
WString itemName = WString::Unmanaged(L"item");
|
|
if (indexItemName != -1)
|
|
{
|
|
const auto& values = resolvingResult.envVars.GetByIndex(indexItemName);
|
|
itemName = values[values.Count() - 1]->value;
|
|
}
|
|
|
|
if (auto refExpr = propertyExpression.Cast<WfReferenceExpression>())
|
|
{
|
|
if (refExpr->name.value != itemName)
|
|
{
|
|
auto refItem = Ptr(new WfReferenceExpression);
|
|
refItem->name.value = itemName;
|
|
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = refItem;
|
|
member->name.value = refExpr->name.value;
|
|
|
|
propertyExpression = member;
|
|
}
|
|
}
|
|
|
|
bool isWritableItemProperty = IsWritableItemPropertyType(typeInfo);
|
|
|
|
auto funcDecl = Ptr(new WfFunctionDeclaration);
|
|
ITypeInfo* acceptValueType = nullptr;
|
|
funcDecl->functionKind = WfFunctionKind::Normal;
|
|
funcDecl->anonymity = WfFunctionAnonymity::Anonymous;
|
|
{
|
|
auto genericType = typeInfo->GetElementType();
|
|
funcDecl->returnType = GetTypeFromTypeInfo(genericType->GetGenericArgument(0));
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<item>";
|
|
argument->type = GetTypeFromTypeInfo(genericType->GetGenericArgument(1));
|
|
funcDecl->arguments.Add(argument);
|
|
}
|
|
|
|
if (isWritableItemProperty)
|
|
{
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<value>";
|
|
argument->type = GetTypeFromTypeInfo((acceptValueType = genericType->GetGenericArgument(2)));
|
|
funcDecl->arguments.Add(argument);
|
|
}
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<update>";
|
|
argument->type = GetTypeFromTypeInfo(genericType->GetGenericArgument(3));
|
|
funcDecl->arguments.Add(argument);
|
|
}
|
|
}
|
|
}
|
|
|
|
auto funcBlock = Ptr(new WfBlockStatement);
|
|
funcDecl->statement = funcBlock;
|
|
|
|
{
|
|
auto refItem = Ptr(new WfReferenceExpression);
|
|
refItem->name.value = L"<item>";
|
|
|
|
auto refCast = Ptr(new WfTypeCastingExpression);
|
|
refCast->strategy = WfTypeCastingStrategy::Strong;
|
|
refCast->type = itemType;
|
|
refCast->expression = refItem;
|
|
|
|
auto varDecl = Ptr(new WfVariableDeclaration);
|
|
varDecl->name.value = itemName;
|
|
varDecl->expression = refCast;
|
|
|
|
auto varStat = Ptr(new WfVariableStatement);
|
|
varStat->variable = varDecl;
|
|
funcBlock->statements.Add(varStat);
|
|
}
|
|
|
|
Ptr<WfReturnStatement> returnStat;
|
|
{
|
|
returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = propertyExpression;
|
|
}
|
|
|
|
if (isWritableItemProperty)
|
|
{
|
|
auto ifStat = Ptr(new WfIfStatement);
|
|
funcBlock->statements.Add(ifStat);
|
|
{
|
|
auto refUpdate = Ptr(new WfReferenceExpression);
|
|
refUpdate->name.value = L"<update>";
|
|
|
|
ifStat->expression = refUpdate;
|
|
}
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
ifStat->trueBranch = block;
|
|
|
|
{
|
|
auto refValue = Ptr(new WfReferenceExpression);
|
|
refValue->name.value = L"<value>";
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
assignExpr->first = CopyExpression(propertyExpression, true);
|
|
|
|
if (acceptValueType->GetTypeDescriptor()->GetTypeDescriptorFlags() == TypeDescriptorFlags::Object)
|
|
{
|
|
auto castExpr = Ptr(new WfExpectedTypeCastExpression);
|
|
castExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
castExpr->expression = refValue;
|
|
assignExpr->second = castExpr;
|
|
}
|
|
else
|
|
{
|
|
assignExpr->second = refValue;
|
|
}
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assignExpr;
|
|
block->statements.Add(stat);
|
|
}
|
|
{
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
block->statements.Add(returnStat);
|
|
|
|
auto returnType = typeInfo->GetElementType()->GetGenericArgument(0);
|
|
returnStat->expression = CreateDefaultValue(returnType);
|
|
}
|
|
}
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
ifStat->falseBranch = block;
|
|
|
|
block->statements.Add(returnStat);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
funcBlock->statements.Add(returnStat);
|
|
}
|
|
|
|
auto funcExpr = Ptr(new WfFunctionExpression);
|
|
funcExpr->function = funcDecl;
|
|
return funcExpr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiDataProcessorDeserializer
|
|
***********************************************************************/
|
|
|
|
class GuiDataProcessorDeserializer : public Object, public IGuiInstanceDeserializer
|
|
{
|
|
protected:
|
|
Ptr<ITypeInfo> stringType;
|
|
|
|
public:
|
|
GuiDataProcessorDeserializer()
|
|
{
|
|
stringType = TypeInfoRetriver<WString>::CreateTypeInfo();
|
|
}
|
|
|
|
bool CanDeserialize(const IGuiInstanceLoader::PropertyInfo& propertyInfo, description::ITypeInfo* typeInfo)override
|
|
{
|
|
return typeInfo->GetTypeDescriptor() == description::GetTypeDescriptor<IDataFilter>()
|
|
|| typeInfo->GetTypeDescriptor() == description::GetTypeDescriptor<IDataSorter>();
|
|
}
|
|
|
|
description::ITypeInfo* DeserializeAs(const IGuiInstanceLoader::PropertyInfo& propertyInfo, description::ITypeInfo* typeInfo)override
|
|
{
|
|
return stringType.Obj();
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> Deserialize(
|
|
GuiResourcePrecompileContext& precompileContext,
|
|
types::ResolvingResult& resolvingResult,
|
|
const IGuiInstanceLoader::PropertyInfo& propertyInfo,
|
|
description::ITypeInfo* typeInfo,
|
|
Ptr<workflow::WfExpression> valueExpression,
|
|
GuiResourceTextPos tagPosition,
|
|
GuiResourceError::List& errors
|
|
)override
|
|
{
|
|
auto stringExpr = valueExpression.Cast<WfStringExpression>();
|
|
Ptr<WfExpression> propertyExpression;
|
|
{
|
|
propertyExpression = Workflow_ParseExpression(precompileContext, { resolvingResult.resource }, stringExpr->value.value, tagPosition, errors);
|
|
if (!propertyExpression)
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
vint indexItemType = resolvingResult.envVars.Keys().IndexOf(GlobalStringKey::Get(L"ItemType"));
|
|
if (indexItemType == -1)
|
|
{
|
|
auto error
|
|
= L"Precompile: env.ItemType must be specified before deserializing \""
|
|
+ stringExpr->value.value
|
|
+ L"\" to value of type \""
|
|
+ typeInfo->GetTypeFriendlyName()
|
|
+ L"\".";
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, tagPosition, error));
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<WfType> itemType;
|
|
{
|
|
const auto& values = resolvingResult.envVars.GetByIndex(indexItemType);
|
|
auto itemTypeValue = values[values.Count() - 1];
|
|
|
|
itemType = Workflow_ParseType(precompileContext, { resolvingResult.resource }, itemTypeValue->value, itemTypeValue->valuePosition, errors);
|
|
if (!itemType)
|
|
{
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
auto newExpr = Ptr(new WfNewInterfaceExpression);
|
|
newExpr->type = GetTypeFromTypeInfo(typeInfo);
|
|
{
|
|
auto decl = Ptr(new WfFunctionDeclaration);
|
|
newExpr->declarations.Add(decl);
|
|
decl->functionKind = WfFunctionKind::Override;
|
|
decl->name.value = L"SetCallback";
|
|
decl->anonymity = WfFunctionAnonymity::Named;
|
|
decl->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<void>::CreateTypeInfo().Obj());
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->type = GetTypeFromTypeInfo(TypeInfoRetriver<IDataProcessorCallback*>::CreateTypeInfo().Obj());
|
|
argument->name.value = L"value";
|
|
decl->arguments.Add(argument);
|
|
}
|
|
|
|
auto block = Ptr(new WfBlockStatement);
|
|
decl->statement = block;
|
|
}
|
|
{
|
|
auto decl = Ptr(new WfFunctionDeclaration);
|
|
newExpr->declarations.Add(decl);
|
|
decl->functionKind = WfFunctionKind::Override;
|
|
decl->anonymity = WfFunctionAnonymity::Named;
|
|
|
|
List<WString> argumentNames;
|
|
if (typeInfo->GetTypeDescriptor() == description::GetTypeDescriptor<IDataFilter>())
|
|
{
|
|
decl->name.value = L"Filter";
|
|
decl->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<bool>::CreateTypeInfo().Obj());
|
|
argumentNames.Add(L"<row>");
|
|
}
|
|
else
|
|
{
|
|
decl->name.value = L"Compare";
|
|
switch (precompileContext.targetCpuArchitecture)
|
|
{
|
|
case GuiResourceCpuArchitecture::x86:
|
|
decl->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<vint32_t>::CreateTypeInfo().Obj());
|
|
break;
|
|
case GuiResourceCpuArchitecture::x64:
|
|
decl->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<vint64_t>::CreateTypeInfo().Obj());
|
|
break;
|
|
default:
|
|
CHECK_FAIL(L"The target CPU architecture is unspecified.");
|
|
}
|
|
argumentNames.Add(L"<row1>");
|
|
argumentNames.Add(L"<row2>");
|
|
}
|
|
|
|
for (auto name : argumentNames)
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->type = GetTypeFromTypeInfo(TypeInfoRetriver<Value>::CreateTypeInfo().Obj());
|
|
argument->name.value = name;
|
|
decl->arguments.Add(argument);
|
|
}
|
|
|
|
auto block = Ptr(new WfBlockStatement);
|
|
decl->statement = block;
|
|
|
|
auto inferExpr = Ptr(new WfInferExpression);
|
|
inferExpr->expression = propertyExpression;
|
|
{
|
|
auto funcType = Ptr(new WfFunctionType);
|
|
inferExpr->type = funcType;
|
|
|
|
funcType->result = CopyType(decl->returnType);
|
|
for (vint i = 0; i < decl->arguments.Count(); i++)
|
|
{
|
|
funcType->arguments.Add(CopyType(itemType));
|
|
}
|
|
}
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = inferExpr;
|
|
for (auto [name, index] : indexed(argumentNames))
|
|
{
|
|
auto refExpr = Ptr(new WfReferenceExpression);
|
|
refExpr->name.value = name;
|
|
|
|
auto castExpr = Ptr(new WfTypeCastingExpression);
|
|
castExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
castExpr->type = (index == 0 ? itemType : CopyType(itemType));
|
|
castExpr->expression = refExpr;
|
|
|
|
callExpr->arguments.Add(castExpr);
|
|
}
|
|
|
|
auto stat = Ptr(new WfReturnStatement);
|
|
stat->expression = callExpr;
|
|
block->statements.Add(stat);
|
|
}
|
|
return newExpr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiPredefinedInstanceDeserializersPlugin
|
|
***********************************************************************/
|
|
|
|
class GuiPredefinedInstanceDeserializersPlugin : public Object, public IGuiPlugin
|
|
{
|
|
public:
|
|
|
|
GUI_PLUGIN_NAME(GacUI_Instance_Deserializers)
|
|
{
|
|
GUI_PLUGIN_DEPEND(GacUI_Instance);
|
|
}
|
|
|
|
void Load()override
|
|
{
|
|
IGuiInstanceLoaderManager* manager = GetInstanceLoaderManager();
|
|
manager->AddInstanceDeserializer(Ptr(new GuiTemplatePropertyDeserializer));
|
|
manager->AddInstanceDeserializer(Ptr(new GuiItemPropertyDeserializer));
|
|
manager->AddInstanceDeserializer(Ptr(new GuiDataProcessorDeserializer));
|
|
}
|
|
|
|
void Unload()override
|
|
{
|
|
}
|
|
};
|
|
GUI_REGISTER_PLUGIN(GuiPredefinedInstanceDeserializersPlugin)
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\GUIINSTANCELOADER_PREDEFINEDTYPERESOLVERS.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace glr::xml;
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
using namespace workflow::emitter;
|
|
using namespace workflow::runtime;
|
|
using namespace reflection::description;
|
|
using namespace collections;
|
|
using namespace stream;
|
|
|
|
using namespace controls;
|
|
|
|
class WorkflowVirtualScriptPositionVisitor : public workflow::traverse_visitor::AstVisitor
|
|
{
|
|
using BaseVisitor = workflow::traverse_visitor::AstVisitor;
|
|
public:
|
|
GuiResourcePrecompileContext& context;
|
|
Ptr<types::ScriptPosition> sp;
|
|
|
|
WorkflowVirtualScriptPositionVisitor(GuiResourcePrecompileContext& _context)
|
|
:context(_context)
|
|
{
|
|
sp = Workflow_GetScriptPosition(context);
|
|
}
|
|
|
|
void Visit(WfVirtualCfeExpression* node)override
|
|
{
|
|
BaseVisitor::Visit(node);
|
|
vint index = sp->nodePositions.Keys().IndexOf(node);
|
|
if (index != -1)
|
|
{
|
|
auto record = sp->nodePositions.Values()[index];
|
|
Workflow_RecordScriptPosition(context, record.position, node->expandedExpression, record.availableAfter);
|
|
}
|
|
}
|
|
|
|
void Visit(WfVirtualCseExpression* node)override
|
|
{
|
|
BaseVisitor::Visit(node);
|
|
vint index = sp->nodePositions.Keys().IndexOf(node);
|
|
if (index != -1)
|
|
{
|
|
auto record = sp->nodePositions.Values()[index];
|
|
Workflow_RecordScriptPosition(context, record.position, node->expandedExpression, record.availableAfter);
|
|
}
|
|
}
|
|
|
|
void Visit(WfVirtualCseStatement* node)override
|
|
{
|
|
BaseVisitor::Visit(node);
|
|
vint index = sp->nodePositions.Keys().IndexOf(node);
|
|
if (index != -1)
|
|
{
|
|
auto record = sp->nodePositions.Values()[index];
|
|
Workflow_RecordScriptPosition(context, record.position, node->expandedStatement, record.availableAfter);
|
|
}
|
|
}
|
|
|
|
void Visit(WfVirtualCfeDeclaration* node)override
|
|
{
|
|
BaseVisitor::Visit(node);
|
|
vint index = sp->nodePositions.Keys().IndexOf(node);
|
|
if (index != -1)
|
|
{
|
|
auto record = sp->nodePositions.Values()[index];
|
|
for (auto decl : node->expandedDeclarations)
|
|
{
|
|
Workflow_RecordScriptPosition(context, record.position, decl, record.availableAfter);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Visit(WfVirtualCseDeclaration* node)override
|
|
{
|
|
BaseVisitor::Visit(node);
|
|
vint index = sp->nodePositions.Keys().IndexOf(node);
|
|
if (index != -1)
|
|
{
|
|
auto record = sp->nodePositions.Values()[index];
|
|
for (auto decl : node->expandedDeclarations)
|
|
{
|
|
Workflow_RecordScriptPosition(context, record.position, decl, record.availableAfter);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
Ptr<GuiInstanceCompiledWorkflow> Workflow_GetModule(GuiResourcePrecompileContext& context, const WString& path, Nullable<GuiInstanceCompiledWorkflow::AssemblyType> assemblyType)
|
|
{
|
|
auto compiled = context.targetFolder->GetValueByPath(path).Cast<GuiInstanceCompiledWorkflow>();
|
|
if (assemblyType && !compiled)
|
|
{
|
|
compiled = Ptr(new GuiInstanceCompiledWorkflow);
|
|
compiled->type = assemblyType.Value();
|
|
context.targetFolder->CreateValueByPath(path, L"Workflow", compiled);
|
|
}
|
|
return compiled;
|
|
}
|
|
|
|
void Workflow_AddModule(GuiResourcePrecompileContext& context, const WString& path, Ptr<WfModule> module, GuiInstanceCompiledWorkflow::AssemblyType assemblyType, GuiResourceTextPos tagPosition)
|
|
{
|
|
auto compiled = Workflow_GetModule(context, path, assemblyType);
|
|
CHECK_ERROR(compiled->type == assemblyType, L"Workflow_AddModule(GuiResourcePrecompiledContext&, const WString&, GuiInstanceCompiledWorkflow::AssemblyType)#Unexpected assembly type.");
|
|
|
|
GuiInstanceCompiledWorkflow::ModuleRecord record;
|
|
record.module = module;
|
|
record.position = tagPosition;
|
|
record.shared = assemblyType == GuiInstanceCompiledWorkflow::Shared;
|
|
compiled->modules.Add(record);
|
|
}
|
|
|
|
void Workflow_GenerateAssembly(GuiResourcePrecompileContext& context, const WString& path, GuiResourceError::List& errors, bool keepMetadata, IWfCompilerCallback* compilerCallback)
|
|
{
|
|
auto compiled = Workflow_GetModule(context, path, {});
|
|
if (!compiled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!compiled->assembly)
|
|
{
|
|
List<WString> codes;
|
|
auto manager = Workflow_GetSharedManager(context.targetCpuArchitecture);
|
|
manager->Clear(false, true);
|
|
|
|
auto addCode = [&codes](TextReader& reader)
|
|
{
|
|
vint row = 0;
|
|
WString code;
|
|
while (!reader.IsEnd())
|
|
{
|
|
auto rowHeader = itow(++row);
|
|
while (rowHeader.Length() < 6)
|
|
{
|
|
rowHeader = L" " + rowHeader;
|
|
}
|
|
code += rowHeader + L" : " + reader.ReadLine() + L"\r\n";
|
|
}
|
|
codes.Add(code);
|
|
};
|
|
|
|
for (vint i = 0; i < compiled->modules.Count(); i++)
|
|
{
|
|
manager->AddModule(compiled->modules[i].module);
|
|
}
|
|
|
|
if (manager->errors.Count() == 0)
|
|
{
|
|
manager->Rebuild(true, compilerCallback);
|
|
}
|
|
|
|
if (manager->errors.Count() == 0)
|
|
{
|
|
compiled->assembly = GenerateAssembly(manager, compilerCallback);
|
|
WfAssemblyLoadErrors loadErrors;
|
|
if (!compiled->Initialize(true, loadErrors))
|
|
{
|
|
glr::ParsingError error;
|
|
error.message = L"Internal error happened during loading an assembly that just passed type verification.";
|
|
manager->errors.Add(error);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (vint i = 0; i < compiled->modules.Count(); i++)
|
|
{
|
|
auto module = compiled->modules[i];
|
|
WorkflowVirtualScriptPositionVisitor visitor(context);
|
|
visitor.InspectInto(module.module.Obj());
|
|
Workflow_RecordScriptPosition(context, module.position, module.module);
|
|
}
|
|
|
|
auto sp = Workflow_GetScriptPosition(context);
|
|
for (vint i = 0; i < manager->errors.Count(); i++)
|
|
{
|
|
auto error = manager->errors[i];
|
|
errors.Add({ sp->nodePositions[error.node].computedPosition, error.message });
|
|
}
|
|
}
|
|
|
|
if (keepMetadata)
|
|
{
|
|
compiled->metadata = Workflow_TransferSharedManager();
|
|
}
|
|
else
|
|
{
|
|
manager->Clear(false, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
Shared Script Type Resolver (Script)
|
|
***********************************************************************/
|
|
|
|
#define Path_Shared L"Workflow/Shared"
|
|
#define Path_TemporaryClass L"Workflow/TemporaryClass"
|
|
#define Path_InstanceClass L"Workflow/InstanceClass"
|
|
|
|
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 Workflow_Max;
|
|
}
|
|
|
|
PassSupport GetPassSupport(vint passIndex)override
|
|
{
|
|
switch (passIndex)
|
|
{
|
|
case Workflow_Collect:
|
|
return PerResource;
|
|
case Workflow_Compile:
|
|
return PerPass;
|
|
default:
|
|
return NotSupported;
|
|
}
|
|
}
|
|
|
|
void PerResourcePrecompile(Ptr<GuiResourceItem> resource, GuiResourcePrecompileContext& context, GuiResourceError::List& errors)override
|
|
{
|
|
switch (context.passIndex)
|
|
{
|
|
case Workflow_Collect:
|
|
{
|
|
if (auto obj = resource->GetContent().Cast<GuiInstanceSharedScript>())
|
|
{
|
|
if (obj->language == L"Workflow")
|
|
{
|
|
if (auto module = Workflow_ParseModule(context, obj->codePosition.originalLocation, obj->code, obj->codePosition, errors))
|
|
{
|
|
Workflow_AddModule(context, Path_Shared, module, GuiInstanceCompiledWorkflow::Shared, obj->codePosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void PerPassPrecompile(GuiResourcePrecompileContext& context, GuiResourceError::List& errors)override
|
|
{
|
|
switch (context.passIndex)
|
|
{
|
|
case Workflow_Compile:
|
|
Workflow_GenerateAssembly(context, Path_Shared, errors, false, context.compilerCallback);
|
|
if (auto compiled = Workflow_GetModule(context, Path_Shared, {}))
|
|
{
|
|
for (vint i = 0; i < compiled->modules.Count(); i++)
|
|
{
|
|
auto& module = compiled->modules[i];
|
|
if (module.module)
|
|
{
|
|
module.module = CopyModule(module.module, true);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
IGuiResourceTypeResolver_Precompile* Precompile()override
|
|
{
|
|
return this;
|
|
}
|
|
|
|
IGuiResourceTypeResolver_IndirectLoad* IndirectLoad()override
|
|
{
|
|
return this;
|
|
}
|
|
|
|
Ptr<DescriptableObject> Serialize(Ptr<GuiResourceItem> resource, Ptr<DescriptableObject> content)override
|
|
{
|
|
if (auto obj = content.Cast<GuiInstanceSharedScript>())
|
|
{
|
|
return obj->SaveToXml();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(Ptr<GuiResourceItem> resource, Ptr<GuiResourcePathResolver> resolver, GuiResourceError::List& errors)override
|
|
{
|
|
if (auto xml = resource->GetContent().Cast<XmlDocument>())
|
|
{
|
|
auto schema = GuiInstanceSharedScript::LoadFromXml(resource, xml, errors);
|
|
return schema;
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
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 Instance_Max;
|
|
}
|
|
|
|
PassSupport GetPassSupport(vint passIndex)override
|
|
{
|
|
switch (passIndex)
|
|
{
|
|
case Workflow_Collect:
|
|
case Instance_CollectInstanceTypes:
|
|
case Instance_CollectEventHandlers:
|
|
case Instance_GenerateInstanceClass:
|
|
return PerResource;
|
|
case Instance_CompileInstanceTypes:
|
|
case Instance_CompileEventHandlers:
|
|
case Instance_CompileInstanceClass:
|
|
return PerPass;
|
|
default:
|
|
return NotSupported;
|
|
}
|
|
}
|
|
|
|
#define ENSURE_ASSEMBLY_EXISTS(PATH, ASSEMBLY_TYPE)\
|
|
if (auto compiled = Workflow_GetModule(context, PATH, GuiInstanceCompiledWorkflow::ASSEMBLY_TYPE))\
|
|
{\
|
|
if (!compiled->assembly)\
|
|
{\
|
|
break;\
|
|
}\
|
|
}\
|
|
else\
|
|
{\
|
|
break;\
|
|
}\
|
|
|
|
#define UNLOAD_ASSEMBLY(PATH)\
|
|
if (auto compiled = Workflow_GetModule(context, PATH, {}))\
|
|
{\
|
|
compiled->UnloadTypes();\
|
|
}\
|
|
|
|
#define DELETE_ASSEMBLY(PATH)\
|
|
if (auto compiled = Workflow_GetModule(context, PATH, {}))\
|
|
{\
|
|
compiled->UnloadAssembly();\
|
|
}\
|
|
|
|
void PerResourcePrecompile(Ptr<GuiResourceItem> resource, GuiResourcePrecompileContext& context, GuiResourceError::List& errors)override
|
|
{
|
|
switch (context.passIndex)
|
|
{
|
|
case Workflow_Collect:
|
|
{
|
|
if (auto obj = resource->GetContent().Cast<GuiInstanceContext>())
|
|
{
|
|
auto record = context.targetFolder->GetValueByPath(L"ClassNameRecord").Cast<GuiResourceClassNameRecord>();
|
|
if (!record)
|
|
{
|
|
record = Ptr(new GuiResourceClassNameRecord);
|
|
context.targetFolder->CreateValueByPath(L"ClassNameRecord", L"ClassNameRecord", record);
|
|
}
|
|
|
|
if (!record->classResources.Keys().Contains(obj->className))
|
|
{
|
|
record->classNames.Add(obj->className);
|
|
record->classResources.Add(obj->className, resource);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case Instance_CollectEventHandlers:
|
|
ENSURE_ASSEMBLY_EXISTS(Path_TemporaryClass, TemporaryClass)
|
|
case Instance_CollectInstanceTypes:
|
|
{
|
|
if (auto obj = resource->GetContent().Cast<GuiInstanceContext>())
|
|
{
|
|
if (obj->className == L"")
|
|
{
|
|
errors.Add(GuiResourceError({ resource }, obj->tagPosition,
|
|
L"Precompile: Instance \"" +
|
|
(obj->instance->typeNamespace == GlobalStringKey::Empty
|
|
? obj->instance->typeName.ToString()
|
|
: obj->instance->typeNamespace.ToString() + L":" + obj->instance->typeName.ToString()
|
|
) +
|
|
L"\" should have the class name specified in the ref.Class attribute."));
|
|
}
|
|
|
|
for (auto [localized, index] :
|
|
indexed(From(obj->localizeds).Where([](Ptr<GuiInstanceLocalized> ls) {return ls->defaultStrings; }))
|
|
)
|
|
{
|
|
if (index > 0)
|
|
{
|
|
errors.Add(GuiResourceError({ resource }, localized->tagPosition, L"Precompile: Only one <ref.LocalizedStrings> can be the default one."));
|
|
}
|
|
}
|
|
|
|
obj->ApplyStyles(resource, context.resolver, errors);
|
|
|
|
types::ResolvingResult resolvingResult;
|
|
resolvingResult.resource = resource;
|
|
resolvingResult.context = obj;
|
|
if (auto module = Workflow_GenerateInstanceClass(context, L"<instance>" + obj->className, resolvingResult, errors, context.passIndex))
|
|
{
|
|
Workflow_AddModule(context, Path_TemporaryClass, module, GuiInstanceCompiledWorkflow::TemporaryClass, obj->tagPosition);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case Instance_GenerateInstanceClass:
|
|
{
|
|
ENSURE_ASSEMBLY_EXISTS(Path_TemporaryClass, TemporaryClass)
|
|
if (auto obj = resource->GetContent().Cast<GuiInstanceContext>())
|
|
{
|
|
vint previousErrorCount = errors.Count();
|
|
|
|
types::ResolvingResult resolvingResult;
|
|
resolvingResult.resource = resource;
|
|
resolvingResult.context = obj;
|
|
resolvingResult.rootTypeInfo = Workflow_CollectReferences(context, resolvingResult, errors);
|
|
|
|
if (errors.Count() == previousErrorCount)
|
|
{
|
|
if (auto ctorModule = Workflow_PrecompileInstanceContext(context, L"<constructor>" + obj->className, resolvingResult, errors))
|
|
{
|
|
if (auto instanceModule = Workflow_GenerateInstanceClass(context, L"<instance>" + obj->className, resolvingResult, errors, context.passIndex))
|
|
{
|
|
Workflow_AddModule(context, Path_InstanceClass, ctorModule, GuiInstanceCompiledWorkflow::InstanceClass, obj->tagPosition);
|
|
Workflow_AddModule(context, Path_InstanceClass, instanceModule, GuiInstanceCompiledWorkflow::InstanceClass, obj->tagPosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void PerPassPrecompile(GuiResourcePrecompileContext& context, GuiResourceError::List& errors)override
|
|
{
|
|
WString path;
|
|
GuiInstanceCompiledWorkflow::AssemblyType assemblyType;
|
|
switch (context.passIndex)
|
|
{
|
|
case Instance_CompileInstanceTypes:
|
|
DELETE_ASSEMBLY(Path_Shared)
|
|
path = Path_TemporaryClass;
|
|
assemblyType = GuiInstanceCompiledWorkflow::TemporaryClass;
|
|
break;
|
|
case Instance_CompileEventHandlers:
|
|
DELETE_ASSEMBLY(Path_TemporaryClass)
|
|
path = Path_TemporaryClass;
|
|
assemblyType = GuiInstanceCompiledWorkflow::TemporaryClass;
|
|
break;
|
|
case Instance_CompileInstanceClass:
|
|
UNLOAD_ASSEMBLY(Path_TemporaryClass)
|
|
path = Path_InstanceClass;
|
|
assemblyType = GuiInstanceCompiledWorkflow::InstanceClass;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
auto sharedCompiled = Workflow_GetModule(context, Path_Shared, {});
|
|
auto compiled = Workflow_GetModule(context, path, assemblyType);
|
|
if (sharedCompiled && compiled)
|
|
{
|
|
CopyFrom(
|
|
compiled->modules,
|
|
From(sharedCompiled->modules)
|
|
.Where([](const GuiInstanceCompiledWorkflow::ModuleRecord& module)
|
|
{
|
|
return module.shared;
|
|
}),
|
|
true
|
|
);
|
|
}
|
|
|
|
switch (context.passIndex)
|
|
{
|
|
case Instance_CompileInstanceTypes:
|
|
Workflow_GenerateAssembly(context, path, errors, false, context.compilerCallback);
|
|
compiled->modules.Clear();
|
|
break;
|
|
case Instance_CompileEventHandlers:
|
|
Workflow_GenerateAssembly(context, path, errors, false, context.compilerCallback);
|
|
break;
|
|
case Instance_CompileInstanceClass:
|
|
Workflow_GenerateAssembly(context, path, errors, true, context.compilerCallback);
|
|
break;
|
|
default:;
|
|
}
|
|
Workflow_ClearScriptPosition(context);
|
|
GetInstanceLoaderManager()->ClearReflectionCache();
|
|
}
|
|
|
|
#undef DELETE_ASSEMBLY
|
|
#undef UNLOAD_ASSEMBLY
|
|
#undef ENSURE_ASSEMBLY_EXISTS
|
|
|
|
IGuiResourceTypeResolver_Precompile* Precompile()override
|
|
{
|
|
return this;
|
|
}
|
|
|
|
IGuiResourceTypeResolver_IndirectLoad* IndirectLoad()override
|
|
{
|
|
return this;
|
|
}
|
|
|
|
Ptr<DescriptableObject> Serialize(Ptr<GuiResourceItem> resource, Ptr<DescriptableObject> content)override
|
|
{
|
|
if (auto obj = content.Cast<GuiInstanceContext>())
|
|
{
|
|
return obj->SaveToXml();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(Ptr<GuiResourceItem> resource, Ptr<GuiResourcePathResolver> resolver, GuiResourceError::List& errors)override
|
|
{
|
|
if (auto xml = resource->GetContent().Cast<XmlDocument>())
|
|
{
|
|
Ptr<GuiInstanceContext> context = GuiInstanceContext::LoadFromXml(resource, xml, errors);
|
|
return context;
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Instance Style Type Resolver (InstanceStyle)
|
|
***********************************************************************/
|
|
|
|
class GuiResourceInstanceStyleTypeResolver
|
|
: 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<DescriptableObject> Serialize(Ptr<GuiResourceItem> resource, Ptr<DescriptableObject> content)override
|
|
{
|
|
if (auto obj = content.Cast<GuiInstanceStyleContext>())
|
|
{
|
|
return obj->SaveToXml();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(Ptr<GuiResourceItem> resource, Ptr<GuiResourcePathResolver> resolver, GuiResourceError::List& errors)override
|
|
{
|
|
if (auto xml = resource->GetContent().Cast<XmlDocument>())
|
|
{
|
|
auto context = GuiInstanceStyleContext::LoadFromXml(resource, xml, errors);
|
|
return context;
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Animation Type Resolver (Animation)
|
|
***********************************************************************/
|
|
|
|
class GuiResourceAnimationTypeResolver
|
|
: public Object
|
|
, public IGuiResourceTypeResolver
|
|
, private IGuiResourceTypeResolver_Precompile
|
|
, private IGuiResourceTypeResolver_IndirectLoad
|
|
{
|
|
public:
|
|
WString GetType()override
|
|
{
|
|
return L"Animation";
|
|
}
|
|
|
|
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 Instance_Max;
|
|
}
|
|
|
|
PassSupport GetPassSupport(vint passIndex)override
|
|
{
|
|
switch (passIndex)
|
|
{
|
|
case Instance_CollectInstanceTypes:
|
|
case Instance_CollectEventHandlers:
|
|
case Instance_GenerateInstanceClass:
|
|
return PerResource;
|
|
default:
|
|
return NotSupported;
|
|
}
|
|
}
|
|
|
|
void PerResourcePrecompile(Ptr<GuiResourceItem> resource, GuiResourcePrecompileContext& context, GuiResourceError::List& errors)override
|
|
{
|
|
bool generateImpl = true;
|
|
auto path = Path_InstanceClass;
|
|
auto assemblyType = GuiInstanceCompiledWorkflow::InstanceClass;
|
|
|
|
switch (context.passIndex)
|
|
{
|
|
case Instance_CollectEventHandlers:
|
|
case Instance_CollectInstanceTypes:
|
|
generateImpl = false;
|
|
path = Path_TemporaryClass;
|
|
assemblyType = GuiInstanceCompiledWorkflow::TemporaryClass;
|
|
case Instance_GenerateInstanceClass:
|
|
{
|
|
if (auto obj = resource->GetContent().Cast<GuiInstanceGradientAnimation>())
|
|
{
|
|
if (auto module = obj->Compile(context, L"<animation>" + obj->className, generateImpl, errors))
|
|
{
|
|
Workflow_AddModule(context, path, module, assemblyType, obj->tagPosition);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void PerPassPrecompile(GuiResourcePrecompileContext& context, GuiResourceError::List& errors)override
|
|
{
|
|
CHECK_FAIL(L"GuiResourceAnimationTypeResolver::PerPassPrecompile(GuiResourcePrecompileContext&, GuiResourceError::List&)#This function should not be called.");
|
|
}
|
|
|
|
IGuiResourceTypeResolver_Precompile* Precompile()override
|
|
{
|
|
return this;
|
|
}
|
|
|
|
IGuiResourceTypeResolver_IndirectLoad* IndirectLoad()override
|
|
{
|
|
return this;
|
|
}
|
|
|
|
Ptr<DescriptableObject> Serialize(Ptr<GuiResourceItem> resource, Ptr<DescriptableObject> content)override
|
|
{
|
|
if (auto obj = content.Cast<GuiInstanceGradientAnimation>())
|
|
{
|
|
return obj->SaveToXml();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(Ptr<GuiResourceItem> resource, Ptr<GuiResourcePathResolver> resolver, GuiResourceError::List& errors)override
|
|
{
|
|
if (auto xml = resource->GetContent().Cast<XmlDocument>())
|
|
{
|
|
if (xml->rootElement->name.value == L"Gradient")
|
|
{
|
|
return GuiInstanceGradientAnimation::LoadFromXml(resource, xml, errors);
|
|
}
|
|
else
|
|
{
|
|
errors.Add({
|
|
{ {resource }, xml->rootElement->codeRange.start },
|
|
L"Precompile: Unknown animation type: \"" + xml->rootElement->name.value + L"\"."
|
|
});
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Localized Strings Type Resolver (LocalizedStrings)
|
|
***********************************************************************/
|
|
|
|
class GuiResourceLocalizedStringsTypeResolver
|
|
: public Object
|
|
, public IGuiResourceTypeResolver
|
|
, private IGuiResourceTypeResolver_Precompile
|
|
, private IGuiResourceTypeResolver_IndirectLoad
|
|
{
|
|
public:
|
|
WString GetType()override
|
|
{
|
|
return L"LocalizedStrings";
|
|
}
|
|
|
|
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 Workflow_Collect + 1;
|
|
}
|
|
|
|
PassSupport GetPassSupport(vint passIndex)override
|
|
{
|
|
switch (passIndex)
|
|
{
|
|
case Workflow_Collect:
|
|
return PerResource;
|
|
default:
|
|
return NotSupported;
|
|
}
|
|
}
|
|
|
|
void PerResourcePrecompile(Ptr<GuiResourceItem> resource, GuiResourcePrecompileContext& context, GuiResourceError::List& errors)override
|
|
{
|
|
switch (context.passIndex)
|
|
{
|
|
case Workflow_Collect:
|
|
{
|
|
if (auto obj = resource->GetContent().Cast<GuiInstanceLocalizedStrings>())
|
|
{
|
|
if (auto module = obj->Compile(context, L"<localized-strings>" + obj->className, errors))
|
|
{
|
|
Workflow_AddModule(context, Path_Shared, module, GuiInstanceCompiledWorkflow::Shared, obj->tagPosition);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void PerPassPrecompile(GuiResourcePrecompileContext& context, GuiResourceError::List& errors)override
|
|
{
|
|
CHECK_FAIL(L"GuiResourceLocalizedStringsTypeResolver::PerPassPrecompile(GuiResourcePrecompileContext&, GuiResourceError::List&)#This function should not be called.");
|
|
}
|
|
|
|
IGuiResourceTypeResolver_Precompile* Precompile()override
|
|
{
|
|
return this;
|
|
}
|
|
|
|
IGuiResourceTypeResolver_IndirectLoad* IndirectLoad()override
|
|
{
|
|
return this;
|
|
}
|
|
|
|
Ptr<DescriptableObject> Serialize(Ptr<GuiResourceItem> resource, Ptr<DescriptableObject> content)override
|
|
{
|
|
if (auto obj = content.Cast<GuiInstanceLocalizedStrings>())
|
|
{
|
|
return obj->SaveToXml();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<DescriptableObject> ResolveResource(Ptr<GuiResourceItem> resource, Ptr<GuiResourcePathResolver> resolver, GuiResourceError::List& errors)override
|
|
{
|
|
if (auto xml = resource->GetContent().Cast<XmlDocument>())
|
|
{
|
|
return GuiInstanceLocalizedStrings::LoadFromXml(resource, xml, errors);
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
#undef Path_Shared
|
|
#undef Path_TemporaryClass
|
|
#undef Path_InstanceClass
|
|
|
|
/***********************************************************************
|
|
Plugin
|
|
***********************************************************************/
|
|
|
|
class GuiCompilerTypeResolversPlugin : public Object, public IGuiPlugin
|
|
{
|
|
public:
|
|
|
|
GUI_PLUGIN_NAME(GacUI_Compiler_InstanceTypeResolvers)
|
|
{
|
|
GUI_PLUGIN_DEPEND(GacUI_Res_ResourceResolver);
|
|
}
|
|
|
|
void Load()override
|
|
{
|
|
IGuiResourceResolverManager* manager = GetResourceResolverManager();
|
|
manager->SetTypeResolver(Ptr(new GuiResourceSharedScriptTypeResolver));
|
|
manager->SetTypeResolver(Ptr(new GuiResourceInstanceTypeResolver));
|
|
manager->SetTypeResolver(Ptr(new GuiResourceInstanceStyleTypeResolver));
|
|
manager->SetTypeResolver(Ptr(new GuiResourceAnimationTypeResolver));
|
|
manager->SetTypeResolver(Ptr(new GuiResourceLocalizedStringsTypeResolver));
|
|
}
|
|
|
|
void Unload()override
|
|
{
|
|
}
|
|
};
|
|
GUI_REGISTER_PLUGIN(GuiCompilerTypeResolversPlugin)
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\GUIINSTANCELOCALIZEDSTRINGS.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace collections;
|
|
using namespace glr::xml;
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
using namespace reflection::description;
|
|
|
|
/***********************************************************************
|
|
GuiInstanceLocalizedStrings
|
|
***********************************************************************/
|
|
|
|
WString GuiInstanceLocalizedStrings::Strings::GetLocalesName()
|
|
{
|
|
return From(locales).Aggregate(WString(L""), [](const WString& a, const WString& b)
|
|
{
|
|
return a == L"" ? b : a + L";" + b;
|
|
});
|
|
}
|
|
|
|
Ptr<GuiInstanceLocalizedStrings> GuiInstanceLocalizedStrings::LoadFromXml(Ptr<GuiResourceItem> resource, Ptr<glr::xml::XmlDocument> xml, GuiResourceError::List& errors)
|
|
{
|
|
auto ls = Ptr(new GuiInstanceLocalizedStrings);
|
|
|
|
if (xml->rootElement->name.value!=L"LocalizedStrings")
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xml->rootElement->codeRange.start }, L"Precompile: The root element of localized strings should be \"LocalizedStrings\"."));
|
|
return nullptr;
|
|
}
|
|
ls->tagPosition = { {resource},xml->rootElement->name.codeRange.start };
|
|
|
|
auto attClassName = XmlGetAttribute(xml->rootElement, L"ref.Class");
|
|
if (!attClassName)
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xml->rootElement->codeRange.start }, L"Precompile: Missing attribute \"ref.Class\" in \"LocalizedStrings\"."));
|
|
}
|
|
else
|
|
{
|
|
ls->className = attClassName->value.value;
|
|
}
|
|
|
|
auto attDefaultLocale = XmlGetAttribute(xml->rootElement, L"DefaultLocale");
|
|
if (!attDefaultLocale)
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xml->rootElement->codeRange.start }, L"Precompile: Missing attribute \"DefaultLocale\" in \"LocalizedStrings\"."));
|
|
}
|
|
else
|
|
{
|
|
ls->defaultLocale = attDefaultLocale->value.value;
|
|
}
|
|
|
|
if (!attClassName || !attDefaultLocale)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
SortedList<WString> existingLocales;
|
|
for (auto xmlStrings : XmlGetElements(xml->rootElement))
|
|
{
|
|
if (xmlStrings->name.value != L"Strings")
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xmlStrings->codeRange.start }, L"Precompile: Unknown element \"" + xmlStrings->name.value + L"\", it should be \"Strings\"."));
|
|
continue;
|
|
}
|
|
|
|
auto attLocales = XmlGetAttribute(xmlStrings, L"Locales");
|
|
if (!attLocales)
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xmlStrings->codeRange.start }, L"Precompile: Missing attribute \"Locales\" in \"Strings\"."));
|
|
}
|
|
else
|
|
{
|
|
auto lss = Ptr(new GuiInstanceLocalizedStrings::Strings);
|
|
ls->strings.Add(lss);
|
|
lss->tagPosition = { { resource },xmlStrings->name.codeRange.start };
|
|
SplitBySemicolon(attLocales->value.value, lss->locales);
|
|
|
|
for (auto locale : lss->locales)
|
|
{
|
|
if (!existingLocales.Contains(locale))
|
|
{
|
|
existingLocales.Add(locale);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },attLocales->codeRange.start }, L"Precompile: Locale \"" + locale + L"\" already exists."));
|
|
}
|
|
}
|
|
|
|
for (auto xmlString : XmlGetElements(xmlStrings))
|
|
{
|
|
if (xmlString->name.value != L"String")
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xmlString->codeRange.start }, L"Precompile: Unknown element \"" + xmlString->name.value + L"\", it should be \"String\"."));
|
|
continue;
|
|
}
|
|
|
|
auto attName = XmlGetAttribute(xmlString, L"Name");
|
|
auto attText = XmlGetAttribute(xmlString, L"Text");
|
|
|
|
if (!attName)
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xmlString->codeRange.start }, L"Precompile: Missing attribute \"Name\" in \"String\"."));
|
|
}
|
|
if (!attText)
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xmlString->codeRange.start }, L"Precompile: Missing attribute \"Text\" in \"String\"."));
|
|
}
|
|
|
|
if (attName && attText)
|
|
{
|
|
if (lss->items.Keys().Contains(attName->value.value))
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xmlString->codeRange.start }, L"Precompile: String \"" + attName->value.value + L"\" already exists."));
|
|
}
|
|
else
|
|
{
|
|
auto item = Ptr(new GuiInstanceLocalizedStrings::StringItem);
|
|
item->name = attName->value.value;
|
|
item->text = attText->value.value;
|
|
item->textPosition = { {resource},attText->value.codeRange.start };
|
|
item->textPosition.column += 1;
|
|
lss->items.Add(item->name, item);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!existingLocales.Contains(ls->defaultLocale))
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },xml->rootElement->codeRange.start }, L"Precompile: Strings for the default locale \"" + ls->defaultLocale + L"\" is not defined."));
|
|
}
|
|
|
|
return ls;
|
|
}
|
|
|
|
Ptr<glr::xml::XmlElement> GuiInstanceLocalizedStrings::SaveToXml()
|
|
{
|
|
auto xml = Ptr(new XmlElement);
|
|
xml->name.value = L"LocalizedStrings";
|
|
{
|
|
auto att = Ptr(new XmlAttribute);
|
|
att->name.value = L"ref.Class";
|
|
att->value.value = className;
|
|
xml->attributes.Add(att);
|
|
}
|
|
{
|
|
auto att = Ptr(new XmlAttribute);
|
|
att->name.value = L"DefaultLocale";
|
|
att->value.value = defaultLocale;
|
|
xml->attributes.Add(att);
|
|
}
|
|
|
|
for (auto lss : strings)
|
|
{
|
|
auto xmlStrings = Ptr(new XmlElement);
|
|
xml->subNodes.Add(xmlStrings);
|
|
xmlStrings->name.value = L"Strings";
|
|
{
|
|
auto att = Ptr(new XmlAttribute);
|
|
att->name.value = L"Strings";
|
|
att->value.value = lss->GetLocalesName();
|
|
xmlStrings->attributes.Add(att);
|
|
}
|
|
|
|
for (auto lssi : lss->items.Values())
|
|
{
|
|
auto xmlString = Ptr(new XmlElement);
|
|
xmlStrings->subNodes.Add(xmlString);
|
|
{
|
|
auto att = Ptr(new XmlAttribute);
|
|
att->name.value = L"Name";
|
|
att->value.value = lssi->name;
|
|
xmlString->attributes.Add(att);
|
|
}
|
|
{
|
|
auto att = Ptr(new XmlAttribute);
|
|
att->name.value = L"Text";
|
|
att->value.value = lssi->text;
|
|
xmlString->attributes.Add(att);
|
|
}
|
|
}
|
|
}
|
|
|
|
return xml;
|
|
}
|
|
|
|
Ptr<GuiInstanceLocalizedStrings::Strings> GuiInstanceLocalizedStrings::GetDefaultStrings()
|
|
{
|
|
return From(strings)
|
|
.Where([=](Ptr<Strings> strings)
|
|
{
|
|
return strings->locales.Contains(defaultLocale);
|
|
})
|
|
.First();
|
|
}
|
|
|
|
WString GuiInstanceLocalizedStrings::GetInterfaceTypeName(bool hasNamespace)
|
|
{
|
|
auto pair = INVLOC.FindLast(className, L"::", Locale::None);
|
|
if (pair.key == -1)
|
|
{
|
|
return L"I" + className + L"Strings";
|
|
}
|
|
else
|
|
{
|
|
auto ns = className.Left(pair.key + 2);
|
|
auto name = className.Right(className.Length() - ns.Length());
|
|
return(hasNamespace ? ns : L"") + L"I" + name + L"Strings";
|
|
}
|
|
}
|
|
|
|
Ptr<GuiInstanceLocalizedStrings::TextDesc> GuiInstanceLocalizedStrings::ParseLocalizedText(const WString& text, GuiResourceTextPos pos, GuiResourceError::List& errors)
|
|
{
|
|
const wchar_t* reading = text.Buffer();
|
|
const wchar_t* textPosCounter = reading;
|
|
glr::ParsingTextPos formatPos(0, 0);
|
|
auto textDesc = Ptr(new TextDesc);
|
|
|
|
auto addError = [&](const WString& message)
|
|
{
|
|
auto errorPos = pos;
|
|
errorPos.row += formatPos.row;
|
|
errorPos.column = (formatPos.row == 0 ? errorPos.column : 0) + formatPos.column;
|
|
errors.Add({ errorPos,message });
|
|
};
|
|
|
|
bool addedParameter = true;
|
|
while (*reading)
|
|
{
|
|
const wchar_t* begin = wcsstr(reading, L"$(");
|
|
if (begin)
|
|
{
|
|
auto text = WString::CopyFrom(reading, vint(begin - reading));
|
|
if (addedParameter)
|
|
{
|
|
textDesc->texts.Add(text);
|
|
}
|
|
else
|
|
{
|
|
textDesc->texts[textDesc->texts.Count() - 1] += text;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
const wchar_t* end = wcsstr(begin, L")");
|
|
if (!end)
|
|
{
|
|
addError(L"Precompile: Does not find matched close bracket.");
|
|
return nullptr;
|
|
}
|
|
|
|
while (textPosCounter++ < begin + 2)
|
|
{
|
|
switch (textPosCounter[-1])
|
|
{
|
|
case '\n':
|
|
formatPos.row++;
|
|
formatPos.column = 0;
|
|
break;
|
|
default:
|
|
formatPos.column++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (end - begin == 3 && wcsncmp(begin, L"$($)", 4) == 0)
|
|
{
|
|
addedParameter = false;
|
|
textDesc->texts[textDesc->texts.Count() - 1] += L"$";
|
|
}
|
|
else
|
|
{
|
|
addedParameter = true;
|
|
const wchar_t* number = begin + 2;
|
|
const wchar_t* numberEnd = number;
|
|
while (L'0' <= *numberEnd && *numberEnd < L'9')
|
|
{
|
|
numberEnd++;
|
|
}
|
|
|
|
if (number == numberEnd)
|
|
{
|
|
addError(L"Precompile: Unexpected character, the correct format is $(index) or $(index:function).");
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<ITypeInfo> type;
|
|
WString function;
|
|
if (*numberEnd == L':')
|
|
{
|
|
if (end - numberEnd > 1)
|
|
{
|
|
function = WString::CopyFrom(numberEnd + 1, (vint)(end - numberEnd - 1));
|
|
if (function == L"ShortDate" || function == L"LongDate" || function == L"YearMonthDate" || function == L"ShortTime" || function == L"LongTime")
|
|
{
|
|
type = TypeInfoRetriver<DateTime>::CreateTypeInfo();
|
|
}
|
|
else if (function.Length() >= 5 && (function.Left(5) == L"Date:" || function.Left(5) == L"Time:"))
|
|
{
|
|
type = TypeInfoRetriver<DateTime>::CreateTypeInfo();
|
|
}
|
|
else if (function == L"Number" || function == L"Currency")
|
|
{
|
|
type = TypeInfoRetriver<WString>::CreateTypeInfo();
|
|
}
|
|
else
|
|
{
|
|
addError(L"Precompile: Unknown formatting function name \"" + function + L"\".");
|
|
return nullptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
addError(L"Precompile: Unexpected character, the correct format is $(index) or $(index:function).");
|
|
return nullptr;
|
|
}
|
|
}
|
|
else if (numberEnd != end)
|
|
{
|
|
addError(L"Precompile: Unexpected character, the correct format is $(index) or $(index:function).");
|
|
return nullptr;
|
|
}
|
|
|
|
if (!type)
|
|
{
|
|
type = TypeInfoRetriver<WString>::CreateTypeInfo();
|
|
}
|
|
textDesc->parameters.Add({ type,function });
|
|
textDesc->positions.Add(wtoi(WString::CopyFrom(number, (vint)(numberEnd - number))));
|
|
}
|
|
reading = end + 1;
|
|
}
|
|
|
|
if (*reading || textDesc->texts.Count() == 0)
|
|
{
|
|
textDesc->texts.Add(reading);
|
|
}
|
|
|
|
for (auto [i, index] : indexed(From(textDesc->positions).OrderBySelf()))
|
|
{
|
|
if (i != index)
|
|
{
|
|
errors.Add({ pos,L"Precompile: Missing parameter \"" + itow(index) + L"\"." });
|
|
return nullptr;
|
|
}
|
|
}
|
|
return textDesc;
|
|
}
|
|
|
|
void GuiInstanceLocalizedStrings::Validate(TextDescMap& textDescs, GuiResourcePrecompileContext& precompileContext, GuiResourceError::List& errors)
|
|
{
|
|
auto defaultStrings = GetDefaultStrings();
|
|
|
|
vint errorCount = errors.Count();
|
|
for (auto lss : strings)
|
|
{
|
|
if (lss != defaultStrings)
|
|
{
|
|
auto localesName = lss->GetLocalesName();
|
|
|
|
auto missing = From(defaultStrings->items.Keys())
|
|
.Except(lss->items.Keys())
|
|
.Aggregate(WString(L""), [](const WString& a, const WString& b)
|
|
{
|
|
return a == L"" ? b : a + L", " + b;
|
|
});
|
|
|
|
auto extra = From(lss->items.Keys())
|
|
.Except(defaultStrings->items.Keys())
|
|
.Aggregate(WString(L""), [](const WString& a, const WString& b)
|
|
{
|
|
return a == L"" ? b : a + L", " + b;
|
|
});
|
|
|
|
if (missing != L"")
|
|
{
|
|
errors.Add({ lss->tagPosition,L"Precompile: Missing strings for locale \"" + localesName + L"\": " + missing + L"." });
|
|
}
|
|
|
|
if (extra != L"")
|
|
{
|
|
errors.Add({ lss->tagPosition,L"Precompile: Unnecessary strings for locale \"" + localesName + L"\": " + extra + L"." });
|
|
}
|
|
}
|
|
}
|
|
if (errors.Count() != errorCount)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (auto lssi : defaultStrings->items.Values())
|
|
{
|
|
if (auto textDesc = ParseLocalizedText(lssi->text, lssi->textPosition, errors))
|
|
{
|
|
textDescs.Add({ defaultStrings,lssi->name }, textDesc);
|
|
}
|
|
}
|
|
if (errors.Count() != errorCount)
|
|
{
|
|
return;
|
|
}
|
|
|
|
auto defaultLocalesName = defaultStrings->GetLocalesName();
|
|
for (auto lss : strings)
|
|
{
|
|
if (lss != defaultStrings)
|
|
{
|
|
auto localesName = lss->GetLocalesName();
|
|
|
|
for (auto lssi : lss->items.Values())
|
|
{
|
|
if (auto textDesc = ParseLocalizedText(lssi->text, lssi->textPosition, errors))
|
|
{
|
|
textDescs.Add({ lss,lssi->name }, textDesc);
|
|
auto defaultDesc = textDescs[{defaultStrings, lssi->name}];
|
|
if (defaultDesc->parameters.Count() != textDesc->parameters.Count())
|
|
{
|
|
errors.Add({ lss->tagPosition,L"String \"" + lssi->name + L"\" in locales \"" + defaultLocalesName + L"\" and \"" + localesName + L"\" have different numbers of parameters." });
|
|
}
|
|
else
|
|
{
|
|
for (vint i = 0; i < textDesc->parameters.Count(); i++)
|
|
{
|
|
auto defaultParameter = defaultDesc->parameters[defaultDesc->positions[i]];
|
|
auto parameter = textDesc->parameters[textDesc->positions[i]];
|
|
|
|
if (defaultParameter.key->GetTypeDescriptor()->GetTypeName() != parameter.key->GetTypeDescriptor()->GetTypeName())
|
|
{
|
|
errors.Add({ lss->tagPosition,L"Parameter \"" + itow(i) + L"\" in String \"" + lssi->name + L"\" in locales \"" + defaultLocalesName + L"\" and \"" + localesName + L"\" are in different types \"" + defaultParameter.key->GetTypeFriendlyName() + L"\" and \"" + parameter.key->GetTypeFriendlyName() + L"\"." });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (errors.Count() != errorCount)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
Ptr<workflow::WfFunctionDeclaration> GuiInstanceLocalizedStrings::GenerateFunction(Ptr<TextDesc> textDesc, const WString& functionName, workflow::WfFunctionKind functionKind)
|
|
{
|
|
auto func = Ptr(new WfFunctionDeclaration);
|
|
func->functionKind = functionKind;
|
|
func->anonymity = WfFunctionAnonymity::Named;
|
|
func->name.value = functionName;
|
|
func->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<WString>::CreateTypeInfo().Obj());
|
|
for (vint i = 0; i < textDesc->positions.Count(); i++)
|
|
{
|
|
auto type = textDesc->parameters[textDesc->positions[i]];
|
|
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ls>" + itow(i);
|
|
argument->type = GetTypeFromTypeInfo(type.key.Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
|
|
return func;
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> GuiInstanceLocalizedStrings::GenerateStrings(TextDescMap& textDescs, Ptr<Strings> ls)
|
|
{
|
|
auto lsExpr = Ptr(new WfNewInterfaceExpression);
|
|
{
|
|
auto refType = Ptr(new WfReferenceType);
|
|
refType->name.value = GetInterfaceTypeName(false);
|
|
|
|
auto refPointer = Ptr(new WfSharedPointerType);
|
|
refPointer->element = refType;
|
|
|
|
lsExpr->type = refPointer;
|
|
}
|
|
|
|
for (auto lss : ls->items.Values())
|
|
{
|
|
auto textDesc = textDescs[{ls, lss->name}];
|
|
auto func = GenerateFunction(textDesc, lss->name, WfFunctionKind::Override);
|
|
lsExpr->declarations.Add(func);
|
|
|
|
auto block = Ptr(new WfBlockStatement);
|
|
func->statement = block;
|
|
|
|
Ptr<WfExpression> resultExpr;
|
|
|
|
auto appendExpr = [&](Ptr<WfExpression> strExpr)
|
|
{
|
|
if (resultExpr)
|
|
{
|
|
auto binaryExpr = Ptr(new WfBinaryExpression);
|
|
binaryExpr->op = WfBinaryOperator::FlagAnd;
|
|
binaryExpr->first = resultExpr;
|
|
binaryExpr->second = strExpr;
|
|
|
|
resultExpr = binaryExpr;
|
|
}
|
|
else
|
|
{
|
|
resultExpr = strExpr;
|
|
}
|
|
};
|
|
|
|
for (vint i = 0; i < textDesc->parameters.Count(); i++)
|
|
{
|
|
auto varDesc = Ptr(new WfVariableDeclaration);
|
|
varDesc->name.value = L"<ls>_" + itow(i);
|
|
|
|
auto varStat = Ptr(new WfVariableStatement);
|
|
varStat->variable = varDesc;
|
|
block->statements.Add(varStat);
|
|
|
|
auto type = textDesc->parameters[i].key;
|
|
auto function = textDesc->parameters[i].value;
|
|
auto index = textDesc->positions[i];
|
|
|
|
if (function == L"ShortDate" || function == L"LongDate" || function == L"YearMonthDate" || function == L"ShortTime" || function == L"LongTime")
|
|
{
|
|
auto refLoc = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Localization>());
|
|
|
|
auto refFormats = Ptr(new WfChildExpression);
|
|
refFormats->parent = refLoc;
|
|
refFormats->name.value = L"Get" + function + L"Formats";
|
|
|
|
auto refLocale = Ptr(new WfReferenceExpression);
|
|
refLocale->name.value = L"<ls>locale";
|
|
|
|
auto callFormats = Ptr(new WfCallExpression);
|
|
callFormats->function = refFormats;
|
|
callFormats->arguments.Add(refLocale);
|
|
|
|
auto refFirst = Ptr(new WfReferenceExpression);
|
|
refFirst->name.value = L"<ls>First";
|
|
|
|
auto callFirst = Ptr(new WfCallExpression);
|
|
{
|
|
callFirst->function = refFirst;
|
|
callFirst->arguments.Add(callFormats);
|
|
}
|
|
|
|
auto refLocale2 = Ptr(new WfReferenceExpression);
|
|
refLocale2->name.value = L"<ls>locale";
|
|
|
|
auto refParameter = Ptr(new WfReferenceExpression);
|
|
refParameter->name.value = L"<ls>" + itow(index);
|
|
|
|
auto refLoc2 = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Localization>());
|
|
|
|
auto refFD = Ptr(new WfChildExpression);
|
|
refFD->parent = refLoc2;
|
|
refFD->name.value = L"Format" + function.Right(4);
|
|
|
|
auto callFD = Ptr(new WfCallExpression);
|
|
callFD->function = refFD;
|
|
callFD->arguments.Add(refLocale2);
|
|
callFD->arguments.Add(callFirst);
|
|
callFD->arguments.Add(refParameter);
|
|
|
|
varDesc->expression = callFD;
|
|
}
|
|
else if (function.Length() >= 5 && (function.Left(5) == L"Date:" || function.Left(5) == L"Time:"))
|
|
{
|
|
auto refLocale = Ptr(new WfReferenceExpression);
|
|
refLocale->name.value = L"<ls>locale";
|
|
|
|
auto refFormat = Ptr(new WfStringExpression);
|
|
refFormat->value.value = function.Right(function.Length() - 5);
|
|
|
|
auto refParameter = Ptr(new WfReferenceExpression);
|
|
refParameter->name.value = L"<ls>" + itow(index);
|
|
|
|
auto refLoc2 = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Localization>());
|
|
|
|
auto refFD = Ptr(new WfChildExpression);
|
|
refFD->parent = refLoc2;
|
|
refFD->name.value = L"Format" + function.Left(4);
|
|
|
|
auto callFD = Ptr(new WfCallExpression);
|
|
callFD->function = refFD;
|
|
callFD->arguments.Add(refLocale);
|
|
callFD->arguments.Add(refFormat);
|
|
callFD->arguments.Add(refParameter);
|
|
|
|
varDesc->expression = callFD;
|
|
}
|
|
else if (function == L"Number" || function == L"Currency")
|
|
{
|
|
auto refLocale = Ptr(new WfReferenceExpression);
|
|
refLocale->name.value = L"<ls>locale";
|
|
|
|
auto refParameter = Ptr(new WfReferenceExpression);
|
|
refParameter->name.value = L"<ls>" + itow(index);
|
|
|
|
auto refLoc2 = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<Localization>());
|
|
|
|
auto refFD = Ptr(new WfChildExpression);
|
|
refFD->parent = refLoc2;
|
|
refFD->name.value = L"Format" + function;
|
|
|
|
auto callFD = Ptr(new WfCallExpression);
|
|
callFD->function = refFD;
|
|
callFD->arguments.Add(refLocale);
|
|
callFD->arguments.Add(refParameter);
|
|
|
|
varDesc->expression = callFD;
|
|
}
|
|
else
|
|
{
|
|
auto refParameter = Ptr(new WfReferenceExpression);
|
|
refParameter->name.value = L"<ls>" + itow(index);
|
|
|
|
varDesc->expression = refParameter;
|
|
}
|
|
}
|
|
|
|
for (vint i = 0; i < textDesc->texts.Count(); i++)
|
|
{
|
|
if (textDesc->texts[i] != L"")
|
|
{
|
|
auto strExpr = Ptr(new WfStringExpression);
|
|
strExpr->value.value = textDesc->texts[i];
|
|
appendExpr(strExpr);
|
|
}
|
|
|
|
if (i < textDesc->parameters.Count())
|
|
{
|
|
auto refExpr = Ptr(new WfReferenceExpression);
|
|
refExpr->name.value = L"<ls>_" + itow(i);
|
|
appendExpr(refExpr);
|
|
}
|
|
}
|
|
|
|
if (!resultExpr)
|
|
{
|
|
resultExpr = Ptr(new WfStringExpression);
|
|
}
|
|
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = resultExpr;
|
|
|
|
block->statements.Add(returnStat);
|
|
}
|
|
|
|
return lsExpr;
|
|
}
|
|
|
|
Ptr<workflow::WfModule> GuiInstanceLocalizedStrings::Compile(GuiResourcePrecompileContext& precompileContext, const WString& moduleName, GuiResourceError::List& errors)
|
|
{
|
|
vint errorCount = errors.Count();
|
|
TextDescMap textDescs;
|
|
Validate(textDescs, precompileContext, errors);
|
|
if (errors.Count() != errorCount)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
auto module = Ptr(new WfModule);
|
|
module->moduleType = WfModuleType::Module;
|
|
module->name.value = moduleName;
|
|
{
|
|
auto lsInterface = Workflow_InstallClass(GetInterfaceTypeName(true), module);
|
|
lsInterface->kind = WfClassKind::Interface;
|
|
lsInterface->constructorType = WfConstructorType::SharedPtr;
|
|
|
|
auto defaultStrings = GetDefaultStrings();
|
|
for (auto functionName : defaultStrings->items.Keys())
|
|
{
|
|
auto func = GenerateFunction(textDescs[{defaultStrings, functionName}], functionName, WfFunctionKind::Normal);
|
|
lsInterface->declarations.Add(func);
|
|
}
|
|
}
|
|
auto lsClass = Workflow_InstallClass(className, module);
|
|
{
|
|
auto func = Ptr(new WfFunctionDeclaration);
|
|
lsClass->declarations.Add(func);
|
|
func->functionKind = WfFunctionKind::Static;
|
|
func->anonymity = WfFunctionAnonymity::Named;
|
|
func->name.value = L"<ls>First";
|
|
func->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<WString>::CreateTypeInfo().Obj());
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->type = GetTypeFromTypeInfo(TypeInfoRetriver<LazyList<WString>>::CreateTypeInfo().Obj());
|
|
argument->name.value = L"<ls>formats";
|
|
func->arguments.Add(argument);
|
|
}
|
|
auto block = Ptr(new WfBlockStatement);
|
|
func->statement = block;
|
|
|
|
{
|
|
auto forStat = Ptr(new WfForEachStatement);
|
|
block->statements.Add(forStat);
|
|
forStat->name.value = L"<ls>format";
|
|
forStat->direction = WfForEachDirection::Normal;
|
|
|
|
auto refArgument = Ptr(new WfReferenceExpression);
|
|
refArgument->name.value = L"<ls>formats";
|
|
forStat->collection = refArgument;
|
|
|
|
auto forBlock = Ptr(new WfBlockStatement);
|
|
forStat->statement = forBlock;
|
|
{
|
|
auto refFormat = Ptr(new WfReferenceExpression);
|
|
refFormat->name.value = L"<ls>format";
|
|
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = refFormat;
|
|
forBlock->statements.Add(returnStat);
|
|
}
|
|
}
|
|
{
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = Ptr(new WfStringExpression);
|
|
block->statements.Add(returnStat);
|
|
}
|
|
}
|
|
{
|
|
auto func = Ptr(new WfFunctionDeclaration);
|
|
lsClass->declarations.Add(func);
|
|
|
|
func->functionKind = WfFunctionKind::Static;
|
|
func->anonymity = WfFunctionAnonymity::Named;
|
|
func->name.value = L"Get";
|
|
{
|
|
auto refType = Ptr(new WfReferenceType);
|
|
refType->name.value = GetInterfaceTypeName(false);
|
|
|
|
auto refPointer = Ptr(new WfSharedPointerType);
|
|
refPointer->element = refType;
|
|
|
|
func->returnType = refPointer;
|
|
}
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ls>locale";
|
|
argument->type = GetTypeFromTypeInfo(TypeInfoRetriver<Locale>::CreateTypeInfo().Obj());
|
|
func->arguments.Add(argument);
|
|
}
|
|
|
|
auto block = Ptr(new WfBlockStatement);
|
|
func->statement = block;
|
|
|
|
auto defaultStrings = GetDefaultStrings();
|
|
for (auto ls : strings)
|
|
{
|
|
if (ls != defaultStrings)
|
|
{
|
|
auto listExpr = Ptr(new WfConstructorExpression);
|
|
for (auto locale : ls->locales)
|
|
{
|
|
auto strExpr = Ptr(new WfStringExpression);
|
|
strExpr->value.value = locale;
|
|
|
|
auto item = Ptr(new WfConstructorArgument);
|
|
item->key = strExpr;
|
|
listExpr->arguments.Add(item);
|
|
}
|
|
|
|
auto refLocale = Ptr(new WfReferenceExpression);
|
|
refLocale->name.value = L"<ls>locale";
|
|
|
|
auto inferExpr = Ptr(new WfInferExpression);
|
|
inferExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<WString>::CreateTypeInfo().Obj());
|
|
inferExpr->expression = refLocale;
|
|
|
|
auto inExpr = Ptr(new WfSetTestingExpression);
|
|
inExpr->test = WfSetTesting::In;
|
|
inExpr->element = inferExpr;
|
|
inExpr->collection = listExpr;
|
|
|
|
auto ifStat = Ptr(new WfIfStatement);
|
|
block->statements.Add(ifStat);
|
|
ifStat->expression = inExpr;
|
|
|
|
auto trueBlock = Ptr(new WfBlockStatement);
|
|
ifStat->trueBranch = trueBlock;
|
|
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = GenerateStrings(textDescs, ls);
|
|
trueBlock->statements.Add(returnStat);
|
|
}
|
|
}
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = GenerateStrings(textDescs, defaultStrings);
|
|
block->statements.Add(returnStat);
|
|
}
|
|
|
|
glr::ParsingTextPos pos(tagPosition.row, tagPosition.column);
|
|
SetCodeRange(module, { pos,pos });
|
|
return module;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\GUIINSTANCEREPRESENTATION.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace collections;
|
|
using namespace glr::xml;
|
|
using namespace templates;
|
|
using namespace stream;
|
|
|
|
/***********************************************************************
|
|
GuiValueRepr
|
|
***********************************************************************/
|
|
|
|
void GuiValueRepr::CloneBody(Ptr<GuiValueRepr> repr)
|
|
{
|
|
repr->fromStyle = fromStyle;
|
|
repr->tagPosition = tagPosition;
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiTextRepr
|
|
***********************************************************************/
|
|
|
|
Ptr<GuiValueRepr> GuiTextRepr::Clone()
|
|
{
|
|
auto repr = Ptr(new GuiTextRepr);
|
|
GuiValueRepr::CloneBody(repr);
|
|
repr->text = text;
|
|
return repr;
|
|
}
|
|
|
|
void GuiTextRepr::FillXml(Ptr<glr::xml::XmlElement> xml)
|
|
{
|
|
if (!fromStyle)
|
|
{
|
|
auto xmlText = Ptr(new XmlText);
|
|
xmlText->content.value = text;
|
|
xml->subNodes.Add(xmlText);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiAttSetterRepr
|
|
***********************************************************************/
|
|
|
|
void GuiAttSetterRepr::CloneBody(Ptr<GuiAttSetterRepr> repr)
|
|
{
|
|
GuiValueRepr::CloneBody(repr);
|
|
|
|
for (auto [name, index] : indexed(setters.Keys()))
|
|
{
|
|
auto src = setters.Values()[index];
|
|
auto dst = Ptr(new SetterValue);
|
|
|
|
dst->binding = src->binding;
|
|
dst->attPosition = src->attPosition;
|
|
for (auto value : src->values)
|
|
{
|
|
dst->values.Add(value->Clone());
|
|
}
|
|
|
|
repr->setters.Add(name, dst);
|
|
}
|
|
|
|
for (auto [name, index] : indexed(eventHandlers.Keys()))
|
|
{
|
|
auto src = eventHandlers.Values()[index];
|
|
auto dst = Ptr(new EventValue);
|
|
|
|
dst->binding = src->binding;
|
|
dst->value = src->value;
|
|
dst->fromStyle = src->fromStyle;
|
|
dst->attPosition = src->attPosition;
|
|
dst->valuePosition = src->valuePosition;
|
|
|
|
repr->eventHandlers.Add(name, dst);
|
|
}
|
|
|
|
for (auto [name, index] : indexed(environmentVariables.Keys()))
|
|
{
|
|
auto src = environmentVariables.Values()[index];
|
|
auto dst = Ptr(new EnvVarValue);
|
|
|
|
dst->value = src->value;
|
|
dst->fromStyle = src->fromStyle;
|
|
dst->attPosition = src->attPosition;
|
|
dst->valuePosition = src->valuePosition;
|
|
|
|
repr->environmentVariables.Add(name, dst);
|
|
}
|
|
|
|
repr->instanceName = instanceName;
|
|
}
|
|
|
|
Ptr<GuiValueRepr> GuiAttSetterRepr::Clone()
|
|
{
|
|
auto repr = Ptr(new GuiAttSetterRepr);
|
|
GuiAttSetterRepr::CloneBody(repr);
|
|
repr->fromStyle = fromStyle;
|
|
return repr;
|
|
}
|
|
|
|
void GuiAttSetterRepr::FillXml(Ptr<glr::xml::XmlElement> xml)
|
|
{
|
|
if (!fromStyle)
|
|
{
|
|
if (instanceName != GlobalStringKey::Empty)
|
|
{
|
|
auto attName = Ptr(new XmlAttribute);
|
|
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)
|
|
{
|
|
for (auto repr : value->values)
|
|
{
|
|
repr->FillXml(xml);
|
|
}
|
|
}
|
|
else if (From(value->values).Any([](Ptr<GuiValueRepr> value) {return !value->fromStyle; }))
|
|
{
|
|
bool containsElement = From(value->values)
|
|
.Any([](Ptr<GuiValueRepr> value)
|
|
{
|
|
return !value->fromStyle && !value.Cast<GuiTextRepr>();
|
|
});
|
|
|
|
if (containsElement)
|
|
{
|
|
auto xmlProp = Ptr(new XmlElement);
|
|
xmlProp->name.value = L"att." + key.ToString();
|
|
if (value->binding != GlobalStringKey::Empty)
|
|
{
|
|
xmlProp->name.value += L"-" + value->binding.ToString();
|
|
}
|
|
|
|
for (auto repr : value->values)
|
|
{
|
|
if (!repr.Cast<GuiTextRepr>())
|
|
{
|
|
repr->FillXml(xmlProp);
|
|
}
|
|
}
|
|
xml->subNodes.Add(xmlProp);
|
|
}
|
|
else
|
|
{
|
|
for (auto repr : value->values)
|
|
{
|
|
if (auto textRepr = repr.Cast<GuiTextRepr>())
|
|
{
|
|
if (!textRepr->fromStyle)
|
|
{
|
|
auto att = Ptr(new XmlAttribute);
|
|
att->name.value = key.ToString();
|
|
if (value->binding != GlobalStringKey::Empty)
|
|
{
|
|
att->name.value += L"-" + value->binding.ToString();
|
|
}
|
|
att->value.value = textRepr->text;
|
|
xml->attributes.Add(att);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (vint i = 0; i < eventHandlers.Count(); i++)
|
|
{
|
|
auto key = eventHandlers.Keys()[i];
|
|
auto value = eventHandlers.Values()[i];
|
|
if (!value->fromStyle)
|
|
{
|
|
auto xmlEvent = Ptr(new XmlElement);
|
|
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 = Ptr(new XmlCData);
|
|
xmlText->content.value = value->value;
|
|
xmlEvent->subNodes.Add(xmlText);
|
|
}
|
|
}
|
|
|
|
for (vint i = 0; i < environmentVariables.Count(); i++)
|
|
{
|
|
auto key = environmentVariables.Keys()[i];
|
|
auto value = environmentVariables.Values()[i];
|
|
if (!value->fromStyle)
|
|
{
|
|
auto xmlEnvVar = Ptr(new XmlElement);
|
|
xmlEnvVar->name.value = L"env." + key.ToString();
|
|
xml->subNodes.Add(xmlEnvVar);
|
|
|
|
auto xmlText = Ptr(new XmlText);
|
|
xmlText->content.value = value->value;
|
|
xmlEnvVar->subNodes.Add(xmlText);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiConstructorRepr
|
|
***********************************************************************/
|
|
|
|
Ptr<GuiValueRepr> GuiConstructorRepr::Clone()
|
|
{
|
|
auto repr = Ptr(new GuiConstructorRepr);
|
|
GuiAttSetterRepr::CloneBody(repr);
|
|
repr->fromStyle = fromStyle;
|
|
repr->typeNamespace = typeNamespace;
|
|
repr->typeName = typeName;
|
|
repr->styleName = styleName;
|
|
return repr;
|
|
}
|
|
|
|
void GuiConstructorRepr::FillXml(Ptr<glr::xml::XmlElement> xml)
|
|
{
|
|
if (!fromStyle)
|
|
{
|
|
auto xmlCtor = Ptr(new XmlElement);
|
|
if (typeNamespace == GlobalStringKey::Empty)
|
|
{
|
|
xmlCtor->name.value = typeName.ToString();
|
|
}
|
|
else
|
|
{
|
|
xmlCtor->name.value = typeNamespace.ToString() + L":" + typeName.ToString();
|
|
}
|
|
|
|
if (styleName)
|
|
{
|
|
auto attStyle = Ptr(new XmlAttribute);
|
|
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(Ptr<GuiResourceItem> resource, GuiAttSetterRepr::ValueList& values, Ptr<glr::xml::XmlElement> xml, GuiResourceError::List& errors)
|
|
{
|
|
if (auto parser = GetParserManager()->GetParser<ElementName>(L"INSTANCE-ELEMENT-NAME"))
|
|
{
|
|
// test if there is only one text value in the xml
|
|
if (xml->subNodes.Count() == 1)
|
|
{
|
|
if (Ptr<XmlText> text = xml->subNodes[0].Cast<XmlText>())
|
|
{
|
|
auto value = Ptr(new GuiTextRepr);
|
|
value->text = text->content.value;
|
|
value->tagPosition = { {resource},text->content.codeRange.start };
|
|
values.Add(value);
|
|
}
|
|
else if (Ptr<XmlCData> text = xml->subNodes[0].Cast<XmlCData>())
|
|
{
|
|
auto value = Ptr(new GuiTextRepr);
|
|
value->text = text->content.value;
|
|
value->tagPosition = { {resource},text->content.codeRange.start };
|
|
value->tagPosition.column += 9; // <![CDATA[
|
|
values.Add(value);
|
|
}
|
|
}
|
|
|
|
// collect default attributes
|
|
for (auto element : XmlGetElements(xml))
|
|
{
|
|
if(auto name = parser->Parse({ resource }, element->name.value, element->codeRange.start, errors))
|
|
{
|
|
if (name->IsCtorName())
|
|
{
|
|
// collect constructor values in the default attribute setter
|
|
auto ctor = LoadCtor(resource, element, errors);
|
|
if (ctor)
|
|
{
|
|
values.Add(ctor);
|
|
}
|
|
}
|
|
else if (!name->IsPropertyElementName() && !name->IsEventElementName())
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},element->codeRange.start }, L"Unknown element name: \"" + element->name.value + L"\"."));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiInstanceContext::CollectAttributes(Ptr<GuiResourceItem> resource, GuiAttSetterRepr::SetteValuerMap& setters, Ptr<glr::xml::XmlElement> xml, GuiResourceError::List& errors)
|
|
{
|
|
if (auto parser = GetParserManager()->GetParser<ElementName>(L"INSTANCE-ELEMENT-NAME"))
|
|
{
|
|
auto defaultValue = Ptr(new GuiAttSetterRepr::SetterValue);
|
|
|
|
// collect default attributes
|
|
CollectDefaultAttributes(resource, defaultValue->values, xml, errors);
|
|
if (defaultValue->values.Count() > 0)
|
|
{
|
|
setters.Add(GlobalStringKey::Empty, defaultValue);
|
|
}
|
|
|
|
// collect values
|
|
for (auto element : XmlGetElements(xml))
|
|
{
|
|
if(auto name = parser->Parse({ resource }, element->name.value, element->name.codeRange.start, errors))
|
|
{
|
|
if (name->IsPropertyElementName())
|
|
{
|
|
// collect a value as a new attribute setter
|
|
if (setters.Keys().Contains(GlobalStringKey::Get(name->name)))
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},element->codeRange.start }, L"Duplicated property \"" + name->name + L"\"."));
|
|
}
|
|
else
|
|
{
|
|
auto sv = Ptr(new GuiAttSetterRepr::SetterValue);
|
|
sv->binding = GlobalStringKey::Get(name->binding);
|
|
sv->attPosition = { {resource},element->codeRange.start };
|
|
|
|
if (name->binding == L"set")
|
|
{
|
|
// if the binding is "set", it means that this element is a complete setter element
|
|
auto setter = Ptr(new GuiAttSetterRepr);
|
|
FillAttSetter(resource, 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(resource, sv->values, element, errors);
|
|
}
|
|
|
|
if (sv->values.Count() > 0)
|
|
{
|
|
setters.Add(GlobalStringKey::Get(name->name), sv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiInstanceContext::CollectEvents(Ptr<GuiResourceItem> resource, GuiAttSetterRepr::EventHandlerMap& eventHandlers, Ptr<glr::xml::XmlElement> xml, GuiResourceError::List& errors)
|
|
{
|
|
if (auto parser = GetParserManager()->GetParser<ElementName>(L"INSTANCE-ELEMENT-NAME"))
|
|
{
|
|
// collect values
|
|
for (auto element : XmlGetElements(xml))
|
|
{
|
|
if(auto name = parser->Parse({ resource }, element->name.value, element->name.codeRange.start, errors))
|
|
{
|
|
if (name->IsEventElementName())
|
|
{
|
|
// collect a value as an event setter
|
|
if (eventHandlers.Keys().Contains(GlobalStringKey::Get(name->name)))
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},element->codeRange.start }, L"Duplicated event \"" + name->name + L"\"."));
|
|
}
|
|
else
|
|
{
|
|
// test if there is only one text value in the xml
|
|
if (element->subNodes.Count() == 1)
|
|
{
|
|
if (Ptr<XmlText> text = element->subNodes[0].Cast<XmlText>())
|
|
{
|
|
auto value = Ptr(new GuiAttSetterRepr::EventValue);
|
|
value->binding = GlobalStringKey::Get(name->binding);
|
|
value->value = text->content.value;
|
|
value->attPosition = { {resource},element->codeRange.start };
|
|
value->valuePosition = { {resource},text->content.codeRange.start };
|
|
eventHandlers.Add(GlobalStringKey::Get(name->name), value);
|
|
if (text->content.codeRange.start.row != text->content.codeRange.end.row)
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},element->codeRange.start }, L"Multiple lines script should be contained in a CDATA section."));
|
|
}
|
|
goto EVENT_SUCCESS;
|
|
}
|
|
else if (Ptr<XmlCData> text = element->subNodes[0].Cast<XmlCData>())
|
|
{
|
|
auto value = Ptr(new GuiAttSetterRepr::EventValue);
|
|
value->binding = GlobalStringKey::Get(name->binding);
|
|
value->value = text->content.value;
|
|
value->attPosition = { {resource},element->codeRange.start };
|
|
value->valuePosition = { {resource},text->content.codeRange.start };
|
|
value->valuePosition.column += 9; // <![CDATA[
|
|
eventHandlers.Add(GlobalStringKey::Get(name->name), value);
|
|
}
|
|
goto EVENT_SUCCESS;
|
|
}
|
|
errors.Add(GuiResourceError({ {resource},element->codeRange.start }, L"Event script should be contained in a text or CDATA section."));
|
|
EVENT_SUCCESS:;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GuiInstanceContext::FillAttSetter(Ptr<GuiResourceItem> resource, Ptr<GuiAttSetterRepr> setter, Ptr<glr::xml::XmlElement> xml, GuiResourceError::List& errors)
|
|
{
|
|
if (auto parser = GetParserManager()->GetParser<ElementName>(L"INSTANCE-ELEMENT-NAME"))
|
|
{
|
|
setter->tagPosition = { {resource},xml->codeRange.start };
|
|
|
|
// collect attributes as setters
|
|
for (auto att : xml->attributes)
|
|
{
|
|
if(auto name = parser->Parse({ resource }, att->name.value, att->name.codeRange.start, errors))
|
|
{
|
|
if (name->IsReferenceAttributeName())
|
|
{
|
|
// collect reference attributes
|
|
if (name->name == L"Name")
|
|
{
|
|
setter->instanceName = GlobalStringKey::Get(att->value.value);
|
|
}
|
|
}
|
|
else if (name->IsEnvironmentAttributeName())
|
|
{
|
|
// collect environment variables
|
|
if (setter->environmentVariables.Keys().Contains(GlobalStringKey::Get(name->name)))
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},att->name.codeRange.start }, L"Duplicated environment variable \"" + name->name + L"\"."));
|
|
}
|
|
else
|
|
{
|
|
auto value = Ptr(new GuiAttSetterRepr::EnvVarValue);
|
|
value->value = att->value.value;
|
|
value->attPosition = { {resource},att->codeRange.start };
|
|
value->valuePosition = { {resource},att->value.codeRange.start };
|
|
value->valuePosition.column += 1;
|
|
setter->environmentVariables.Add(GlobalStringKey::Get(name->name), value);
|
|
}
|
|
}
|
|
else if (name->IsPropertyAttributeName())
|
|
{
|
|
// collect attributes setters
|
|
if (setter->setters.Keys().Contains(GlobalStringKey::Get(name->name)))
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},att->name.codeRange.start }, L"Duplicated property \"" + name->name + L"\"."));
|
|
}
|
|
else
|
|
{
|
|
auto sv = Ptr(new GuiAttSetterRepr::SetterValue);
|
|
sv->binding = GlobalStringKey::Get(name->binding);
|
|
sv->attPosition = { {resource},att->codeRange.start };
|
|
setter->setters.Add(GlobalStringKey::Get(name->name), sv);
|
|
|
|
auto value = Ptr(new GuiTextRepr);
|
|
value->text = att->value.value;
|
|
value->tagPosition = { {resource},att->value.codeRange.start };
|
|
value->tagPosition.column += 1;
|
|
sv->values.Add(value);
|
|
}
|
|
}
|
|
else if (name->IsEventAttributeName())
|
|
{
|
|
// collect event setters
|
|
if (setter->eventHandlers.Keys().Contains(GlobalStringKey::Get(name->name)))
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},att->name.codeRange.start }, L"Duplicated event \"" + name->name + L"\"."));
|
|
}
|
|
else
|
|
{
|
|
auto value = Ptr(new GuiAttSetterRepr::EventValue);
|
|
value->binding = GlobalStringKey::Get(name->binding);
|
|
value->value = att->value.value;
|
|
value->attPosition = { {resource},att->codeRange.start };
|
|
value->valuePosition = { {resource},att->value.codeRange.start };
|
|
value->valuePosition.column += 1;
|
|
setter->eventHandlers.Add(GlobalStringKey::Get(name->name), value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},att->name.codeRange.start }, L"Unknown attribute name: \"" + att->name.value + L"\"."));
|
|
}
|
|
}
|
|
}
|
|
|
|
// collect attributes and events
|
|
CollectAttributes(resource, setter->setters, xml, errors);
|
|
CollectEvents(resource, setter->eventHandlers, xml, errors);
|
|
}
|
|
}
|
|
|
|
Ptr<GuiConstructorRepr> GuiInstanceContext::LoadCtor(Ptr<GuiResourceItem> resource, Ptr<glr::xml::XmlElement> xml, GuiResourceError::List& errors)
|
|
{
|
|
if (auto parser = GetParserManager()->GetParser<ElementName>(L"INSTANCE-ELEMENT-NAME"))
|
|
{
|
|
if(auto ctorName = parser->Parse({ resource }, xml->name.value, xml->name.codeRange.start, errors))
|
|
{
|
|
if (ctorName->IsCtorName())
|
|
{
|
|
auto ctor = Ptr(new GuiConstructorRepr);
|
|
ctor->typeNamespace = GlobalStringKey::Get(ctorName->namespaceName);
|
|
ctor->typeName = GlobalStringKey::Get(ctorName->name);
|
|
// collect attributes as setters
|
|
for (auto att : xml->attributes)
|
|
{
|
|
if(auto attName = parser->Parse({ resource }, att->name.value, att->name.codeRange.start, errors))
|
|
{
|
|
if (attName->IsReferenceAttributeName())
|
|
{
|
|
if (attName->name == L"Style")
|
|
{
|
|
ctor->styleName = att->value.value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
FillAttSetter(resource, ctor, xml, errors);
|
|
return ctor;
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},xml->codeRange.start }, L"Wrong constructor name \"" + xml->name.value + L"\"."));
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Ptr<GuiInstanceContext> GuiInstanceContext::LoadFromXml(Ptr<GuiResourceItem> resource, Ptr<glr::xml::XmlDocument> xml, GuiResourceError::List& errors)
|
|
{
|
|
auto context = Ptr(new GuiInstanceContext);
|
|
context->tagPosition = { {resource},xml->rootElement->codeRange.start };
|
|
|
|
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;
|
|
context->classPosition = { {resource},classAttr->codeRange.start };
|
|
}
|
|
|
|
// load style names
|
|
if (auto styleAttr = XmlGetAttribute(xml->rootElement, L"ref.Styles"))
|
|
{
|
|
SplitBySemicolon(styleAttr->value.value, context->stylePaths);
|
|
context->stylePosition = { {resource},styleAttr->codeRange.start };
|
|
}
|
|
|
|
// load namespaces
|
|
List<Ptr<XmlAttribute>> namespaceAttributes;
|
|
CopyFrom(namespaceAttributes, xml->rootElement->attributes);
|
|
if (!XmlGetAttribute(xml->rootElement, L"xmlns"))
|
|
{
|
|
auto att = Ptr(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::*;"
|
|
L"presentation::theme::*";
|
|
namespaceAttributes.Add(att);
|
|
}
|
|
for (auto 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<NamespaceInfo> info;
|
|
vint index = context->namespaces.Keys().IndexOf(ns);
|
|
if (index == -1)
|
|
{
|
|
info = Ptr(new NamespaceInfo);
|
|
info->name = ns;
|
|
info->attPosition = { {resource},att->codeRange.start };
|
|
context->namespaces.Add(ns, info);
|
|
}
|
|
else
|
|
{
|
|
info = context->namespaces.Values()[index];
|
|
}
|
|
|
|
// extract all patterns in the namespace, split the value by ';'
|
|
List<WString> patterns;
|
|
SplitBySemicolon(att->value.value, patterns);
|
|
for (auto pattern : patterns)
|
|
{
|
|
// add the pattern to the namespace
|
|
auto ns = Ptr(new GuiInstanceNamespace);
|
|
Pair<vint, vint> 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
|
|
for (auto 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 = Ptr(new GuiInstanceParameter);
|
|
parameter->name = GlobalStringKey::Get(attName->value.value);
|
|
parameter->className = GlobalStringKey::Get(attClass->value.value);
|
|
parameter->tagPosition = { {resource},element->codeRange.start };
|
|
parameter->classPosition = { {resource},attClass->value.codeRange.start };
|
|
parameter->classPosition.column += 1;
|
|
context->parameters.Add(parameter);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},element->codeRange.start }, L"ref.Parameter requires the following attributes existing at the same time: Name, Class."));
|
|
}
|
|
}
|
|
else if (element->name.value == L"ref.LocalizedStrings")
|
|
{
|
|
auto attName = XmlGetAttribute(element, L"Name");
|
|
auto attClass = XmlGetAttribute(element, L"Class");
|
|
auto attDefault = XmlGetAttribute(element, L"Default");
|
|
if (attName && attClass)
|
|
{
|
|
auto localized = Ptr(new GuiInstanceLocalized);
|
|
localized->name = GlobalStringKey::Get(attName->value.value);
|
|
localized->className = GlobalStringKey::Get(attClass->value.value);
|
|
localized->tagPosition = { { resource },element->codeRange.start };
|
|
localized->classPosition = { { resource },attClass->value.codeRange.start };
|
|
localized->classPosition.column += 1;
|
|
|
|
if (attDefault)
|
|
{
|
|
localized->defaultStrings = attDefault->value.value == L"true";
|
|
}
|
|
context->localizeds.Add(localized);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ { resource },element->codeRange.start }, L"ref.LocalizedStrings requires the following attributes existing at the same time: Name, Class."));
|
|
}
|
|
}
|
|
|
|
#define COLLECT_SCRIPT(NAME, SCRIPT, POSITION)\
|
|
(element->name.value == L"ref." #NAME)\
|
|
{\
|
|
if (element->subNodes.Count() == 1)\
|
|
{\
|
|
if (auto cdata = element->subNodes[0].Cast<XmlCData>())\
|
|
{\
|
|
context->SCRIPT = cdata->content.value;\
|
|
context->POSITION = { {resource},cdata->codeRange.start };\
|
|
context->POSITION.column += 9; /* <![CDATA[ */\
|
|
goto NAME##_SCRIPT_SUCCESS;\
|
|
}\
|
|
}\
|
|
errors.Add(GuiResourceError({ {resource},element->codeRange.start }, L"Script should be contained in a CDATA section."));\
|
|
NAME##_SCRIPT_SUCCESS:;\
|
|
}\
|
|
|
|
else if COLLECT_SCRIPT(Members, memberScript, memberPosition)
|
|
else if COLLECT_SCRIPT(Ctor, ctorScript, ctorPosition)
|
|
else if COLLECT_SCRIPT(Dtor, dtorScript, dtorPosition)
|
|
|
|
#undef COLLECT_SCRIPT
|
|
else if (!context->instance)
|
|
{
|
|
context->instance = LoadCtor(resource, element, errors);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},xml->rootElement->codeRange.start }, L"The root element of instance should be \"Instance\"."));
|
|
}
|
|
|
|
return context->instance ? context : nullptr;
|
|
}
|
|
|
|
Ptr<glr::xml::XmlDocument> GuiInstanceContext::SaveToXml()
|
|
{
|
|
auto xmlInstance = Ptr(new XmlElement);
|
|
xmlInstance->name.value = L"Instance";
|
|
|
|
{
|
|
auto attCodeBehind = Ptr(new XmlAttribute);
|
|
attCodeBehind->name.value = L"ref.CodeBehind";
|
|
attCodeBehind->value.value = codeBehind ? L"true" : L"false";
|
|
xmlInstance->attributes.Add(attCodeBehind);
|
|
}
|
|
|
|
auto attClass = Ptr(new XmlAttribute);
|
|
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 = Ptr(new XmlAttribute);
|
|
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;
|
|
}
|
|
}
|
|
|
|
for (auto parameter : parameters)
|
|
{
|
|
auto xmlParameter = Ptr(new XmlElement);
|
|
xmlParameter->name.value = L"ref.Parameter";
|
|
xmlInstance->subNodes.Add(xmlParameter);
|
|
|
|
auto attName = Ptr(new XmlAttribute);
|
|
attName->name.value = L"Name";
|
|
attName->value.value = parameter->name.ToString();
|
|
xmlParameter->attributes.Add(attName);
|
|
|
|
auto attClass = Ptr(new XmlAttribute);
|
|
attClass->name.value = L"Class";
|
|
attClass->value.value = parameter->className.ToString();
|
|
xmlParameter->attributes.Add(attClass);
|
|
}
|
|
|
|
for (auto localized : localizeds)
|
|
{
|
|
auto xmlParameter = Ptr(new XmlElement);
|
|
xmlParameter->name.value = L"ref.LocalizedStrings";
|
|
xmlInstance->subNodes.Add(xmlParameter);
|
|
|
|
auto attName = Ptr(new XmlAttribute);
|
|
attName->name.value = L"Name";
|
|
attName->value.value = localized->name.ToString();
|
|
xmlParameter->attributes.Add(attName);
|
|
|
|
auto attClass = Ptr(new XmlAttribute);
|
|
attClass->name.value = L"Class";
|
|
attClass->value.value = localized->className.ToString();
|
|
xmlParameter->attributes.Add(attClass);
|
|
|
|
auto attDefault = Ptr(new XmlAttribute);
|
|
attDefault->name.value = L"Default";
|
|
attDefault->value.value = localized->defaultStrings ? L"true" : L"false";
|
|
xmlParameter->attributes.Add(attDefault);
|
|
}
|
|
|
|
#define SERIALIZE_SCRIPT(NAME, SCRIPT)\
|
|
if (SCRIPT != L"")\
|
|
{\
|
|
auto xmlScript = Ptr(new XmlElement);\
|
|
xmlScript->name.value = L"ref." #NAME;\
|
|
xmlInstance->subNodes.Add(xmlScript);\
|
|
auto text = Ptr(new XmlCData);\
|
|
text->content.value = SCRIPT;\
|
|
xmlScript->subNodes.Add(text);\
|
|
}\
|
|
|
|
SERIALIZE_SCRIPT(Members, memberScript)
|
|
SERIALIZE_SCRIPT(Ctpr, ctorScript)
|
|
SERIALIZE_SCRIPT(Dtor, dtorScript)
|
|
|
|
#undef SERIALIZE_SCRIPT
|
|
|
|
if (stylePaths.Count() > 0)
|
|
{
|
|
auto attStyles = Ptr(new XmlAttribute);
|
|
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 = Ptr(new XmlDocument);
|
|
doc->rootElement = xmlInstance;
|
|
return doc;
|
|
}
|
|
|
|
bool GuiInstanceContext::ApplyStyles(Ptr<GuiResourceItem> resource, Ptr<GuiResourcePathResolver> resolver, GuiResourceError::List& errors)
|
|
{
|
|
if (!appliedStyles)
|
|
{
|
|
appliedStyles = true;
|
|
|
|
List<Ptr<GuiInstanceStyle>> styles;
|
|
for (auto uri : stylePaths)
|
|
{
|
|
WString protocol, path;
|
|
if (IsResourceUrl(uri, protocol, path))
|
|
{
|
|
if (auto styleContext = resolver->ResolveResource(protocol, path).Cast<GuiInstanceStyleContext>())
|
|
{
|
|
CopyFrom(styles, styleContext->styles, true);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resource }, stylePosition, L"Failed to find the style referred in attribute \"ref.Styles\": \"" + uri + L"\"."));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resource }, stylePosition, L"Invalid path in attribute \"ref.Styles\": \"" + uri + L"\"."));
|
|
}
|
|
}
|
|
|
|
for (auto style : styles)
|
|
{
|
|
List<Ptr<GuiConstructorRepr>> output;
|
|
ExecuteQuery(style->query, Ptr(this), output);
|
|
for (auto 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;
|
|
for (auto value : repr->setters.Values())
|
|
{
|
|
for (auto subValue : value->values)
|
|
{
|
|
subValue->Accept(this);
|
|
}
|
|
}
|
|
for (auto value : repr->eventHandlers.Values())
|
|
{
|
|
value->fromStyle = true;
|
|
}
|
|
for (auto value : repr->environmentVariables.Values())
|
|
{
|
|
value->fromStyle = true;
|
|
}
|
|
}
|
|
|
|
void Visit(GuiConstructorRepr* repr)override
|
|
{
|
|
Visit((GuiAttSetterRepr*)repr);
|
|
}
|
|
};
|
|
}
|
|
using namespace visitors;
|
|
|
|
Ptr<GuiInstanceStyle> GuiInstanceStyle::LoadFromXml(Ptr<GuiResourceItem> resource, Ptr<glr::xml::XmlElement> xml, GuiResourceError::List& errors)
|
|
{
|
|
auto style = Ptr(new GuiInstanceStyle);
|
|
if (auto pathAttr = XmlGetAttribute(xml, L"ref.Path"))
|
|
{
|
|
auto position = pathAttr->value.codeRange.start;
|
|
position.column += 1;
|
|
|
|
auto parser = GetParserManager()->GetParser<instancequery::GuiIqQuery>(L"INSTANCE-QUERY");
|
|
auto query = parser->Parse({ resource }, pathAttr->value.value, position, errors);
|
|
if (!query) return nullptr;
|
|
style->query = query;
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},xml->codeRange.start }, L"Missing attribute \"ref.Path\" in <Style>."));
|
|
}
|
|
style->setter = Ptr(new GuiAttSetterRepr);
|
|
GuiInstanceContext::FillAttSetter(resource, style->setter, xml, errors);
|
|
|
|
SetStyleMarkVisitor visitor;
|
|
style->setter->Accept(&visitor);
|
|
return style;
|
|
}
|
|
|
|
Ptr<glr::xml::XmlElement> GuiInstanceStyle::SaveToXml()
|
|
{
|
|
auto xmlStyle = Ptr(new XmlElement);
|
|
xmlStyle->name.value = L"Style";
|
|
|
|
auto attPath = Ptr(new XmlAttribute);
|
|
attPath->name.value = L"ref.Path";
|
|
attPath->value.value = GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
GuiIqPrint(query, writer);
|
|
});
|
|
xmlStyle->attributes.Add(attPath);
|
|
|
|
setter->FillXml(xmlStyle);
|
|
return xmlStyle;
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiInstanceStyleContext
|
|
***********************************************************************/
|
|
|
|
Ptr<GuiInstanceStyleContext> GuiInstanceStyleContext::LoadFromXml(Ptr<GuiResourceItem> resource, Ptr<glr::xml::XmlDocument> xml, GuiResourceError::List& errors)
|
|
{
|
|
auto context = Ptr(new GuiInstanceStyleContext);
|
|
if (xml->rootElement->name.value == L"Styles")
|
|
{
|
|
for (auto styleElement : XmlGetElements(xml->rootElement))
|
|
{
|
|
if (styleElement->name.value == L"Style")
|
|
{
|
|
if (auto style = GuiInstanceStyle::LoadFromXml(resource, styleElement, errors))
|
|
{
|
|
context->styles.Add(style);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},styleElement->codeRange.start }, L"Unknown element in <Styles>: \"" + styleElement->name.value + L"\"."));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ {resource},xml->rootElement->codeRange.start }, L"The root element of instance styles should be \"Styles\"."));
|
|
}
|
|
return context;
|
|
}
|
|
|
|
Ptr<glr::xml::XmlDocument> GuiInstanceStyleContext::SaveToXml()
|
|
{
|
|
auto xmlStyles = Ptr(new XmlElement);
|
|
xmlStyles->name.value = L"Styles";
|
|
|
|
for (auto style : styles)
|
|
{
|
|
xmlStyles->subNodes.Add(style->SaveToXml());
|
|
}
|
|
|
|
auto doc = Ptr(new XmlDocument);
|
|
doc->rootElement = xmlStyles;
|
|
return doc;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\GUIINSTANCESHAREDSCRIPT.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace glr::xml;
|
|
|
|
/***********************************************************************
|
|
GuiInstanceSharedScript
|
|
***********************************************************************/
|
|
|
|
Ptr<GuiInstanceSharedScript> GuiInstanceSharedScript::LoadFromXml(Ptr<GuiResourceItem> resource, Ptr<glr::xml::XmlDocument> xml, GuiResourceError::List& errors)
|
|
{
|
|
if (xml->rootElement->subNodes.Count() == 1)
|
|
{
|
|
if (auto cdata = xml->rootElement->subNodes[0].Cast<XmlCData>())
|
|
{
|
|
auto script = Ptr(new GuiInstanceSharedScript);
|
|
script->language = xml->rootElement->name.value;
|
|
script->code = cdata->content.value;
|
|
script->codePosition = { {resource},cdata->codeRange.start };
|
|
script->codePosition.column += 9; // <![CDATA[
|
|
return script;
|
|
}
|
|
}
|
|
errors.Add(GuiResourceError({ {resource},xml->rootElement->codeRange.start }, L"Script should be contained in a CDATA section."));
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<glr::xml::XmlElement> GuiInstanceSharedScript::SaveToXml()
|
|
{
|
|
auto cdata = Ptr(new XmlCData);
|
|
cdata->content.value = code;
|
|
|
|
auto xml = Ptr(new XmlElement);
|
|
xml->name.value = language;
|
|
xml->subNodes.Add(cdata);
|
|
|
|
return xml;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\INSTANCELOADERS\GUIINSTANCELOADER_COMPOSITIONS.CPP
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
namespace instance_loaders
|
|
{
|
|
|
|
/***********************************************************************
|
|
GuiAxisInstanceLoader
|
|
***********************************************************************/
|
|
|
|
class GuiAxisInstanceLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
GlobalStringKey _AxisDirection;
|
|
|
|
public:
|
|
GuiAxisInstanceLoader()
|
|
{
|
|
typeName = GlobalStringKey::Get(description::TypeInfo<GuiAxis>::content.typeName);
|
|
_AxisDirection = GlobalStringKey::Get(L"AxisDirection");
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
void GetRequiredPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
propertyNames.Add(_AxisDirection);
|
|
}
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _AxisDirection)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<AxisDirection>::CreateTypeInfo());
|
|
info->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
return info;
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
bool CanCreate(const TypeInfo& typeInfo)override
|
|
{
|
|
return typeName == typeInfo.typeName;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> CreateInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos tagPosition, GuiResourceError::List& errors)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
vint indexAxisDirection = arguments.Keys().IndexOf(_AxisDirection);
|
|
if (indexAxisDirection != -1)
|
|
{
|
|
auto createExpr = Ptr(new WfNewClassExpression);
|
|
createExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<Ptr<GuiAxis>>::CreateTypeInfo().Obj());
|
|
createExpr->arguments.Add(arguments.GetByIndex(indexAxisDirection)[0].expression);
|
|
|
|
auto refVariable = Ptr(new WfReferenceExpression);
|
|
refVariable->name.value = variableName.ToString();
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
assignExpr->first = refVariable;
|
|
assignExpr->second = createExpr;
|
|
|
|
auto assignStat = Ptr(new WfExpressionStatement);
|
|
assignStat->expression = assignExpr;
|
|
return assignStat;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiCompositionInstanceLoader
|
|
***********************************************************************/
|
|
|
|
class GuiCompositionInstanceLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
|
|
public:
|
|
GuiCompositionInstanceLoader()
|
|
{
|
|
typeName = GlobalStringKey::Get(description::TypeInfo<GuiGraphicsComposition>::content.typeName);
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
propertyNames.Add(GlobalStringKey::Empty);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == GlobalStringKey::Empty)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Collection(nullptr);
|
|
info->acceptableTypes.Add(TypeInfoRetriver<GuiControl*>::CreateTypeInfo());
|
|
info->acceptableTypes.Add(TypeInfoRetriver<GuiGraphicsComposition*>::CreateTypeInfo());
|
|
info->acceptableTypes.Add(TypeInfoRetriver<Ptr<IGuiGraphicsElement>>::CreateTypeInfo());
|
|
if (propertyInfo.typeInfo.typeInfo->GetTypeDescriptor()->CanConvertTo(description::GetTypeDescriptor<GuiInstanceRootObject>()))
|
|
{
|
|
info->acceptableTypes.Add(TypeInfoRetriver<GuiComponent*>::CreateTypeInfo());
|
|
}
|
|
return info;
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
const auto& values = arguments.GetByIndex(index);
|
|
if (prop == GlobalStringKey::Empty)
|
|
{
|
|
auto value = values[0].expression;
|
|
auto td = values[0].typeInfo->GetTypeDescriptor();
|
|
|
|
Ptr<WfExpression> expr;
|
|
if (td->CanConvertTo(description::GetTypeDescriptor<GuiComponent>()))
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refAddComponent = Ptr(new WfMemberExpression);
|
|
refAddComponent->parent = refControl;
|
|
refAddComponent->name.value = L"AddComponent";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddComponent;
|
|
call->arguments.Add(value);
|
|
|
|
expr = call;
|
|
}
|
|
else if (td->CanConvertTo(description::GetTypeDescriptor<GuiControlHost>()))
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refAddControlHostComponent = Ptr(new WfMemberExpression);
|
|
refAddControlHostComponent->parent = refControl;
|
|
refAddControlHostComponent->name.value = L"AddControlHostComponent";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddControlHostComponent;
|
|
call->arguments.Add(value);
|
|
|
|
expr = call;
|
|
}
|
|
else if (td->CanConvertTo(description::GetTypeDescriptor<IGuiGraphicsElement>()))
|
|
{
|
|
auto refComposition = Ptr(new WfReferenceExpression);
|
|
refComposition->name.value = variableName.ToString();
|
|
|
|
auto refOwnedElement = Ptr(new WfMemberExpression);
|
|
refOwnedElement->parent = refComposition;
|
|
refOwnedElement->name.value = L"OwnedElement";
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refOwnedElement;
|
|
assign->second = value;
|
|
|
|
expr = assign;
|
|
}
|
|
else if (td->CanConvertTo(description::GetTypeDescriptor<GuiControl>()))
|
|
{
|
|
auto refBoundsComposition = Ptr(new WfMemberExpression);
|
|
refBoundsComposition->parent = value;
|
|
refBoundsComposition->name.value = L"BoundsComposition";
|
|
|
|
auto refComposition = Ptr(new WfReferenceExpression);
|
|
refComposition->name.value = variableName.ToString();
|
|
|
|
auto refAddChild = Ptr(new WfMemberExpression);
|
|
refAddChild->parent = refComposition;
|
|
refAddChild->name.value = L"AddChild";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddChild;
|
|
call->arguments.Add(refBoundsComposition);
|
|
|
|
expr = call;
|
|
}
|
|
else if (td->CanConvertTo(description::GetTypeDescriptor<GuiGraphicsComposition>()))
|
|
{
|
|
auto refComposition = Ptr(new WfReferenceExpression);
|
|
refComposition->name.value = variableName.ToString();
|
|
|
|
auto refAddChild = Ptr(new WfMemberExpression);
|
|
refAddChild->parent = refComposition;
|
|
refAddChild->name.value = L"AddChild";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddChild;
|
|
call->arguments.Add(value);
|
|
|
|
expr = call;
|
|
}
|
|
|
|
if (expr)
|
|
{
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = expr;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiTableCompositionInstanceLoader
|
|
***********************************************************************/
|
|
|
|
class GuiTableCompositionInstanceLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
GlobalStringKey _Rows, _Columns;
|
|
|
|
public:
|
|
GuiTableCompositionInstanceLoader()
|
|
{
|
|
typeName = GlobalStringKey::Get(description::TypeInfo<GuiTableComposition>::content.typeName);
|
|
_Rows = GlobalStringKey::Get(L"Rows");
|
|
_Columns = GlobalStringKey::Get(L"Columns");
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
propertyNames.Add(_Rows);
|
|
propertyNames.Add(_Columns);
|
|
}
|
|
|
|
void GetPairedProperties(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (propertyInfo.propertyName == _Rows || propertyInfo.propertyName == _Columns)
|
|
{
|
|
propertyNames.Add(_Rows);
|
|
propertyNames.Add(_Columns);
|
|
}
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _Rows || propertyInfo.propertyName == _Columns)
|
|
{
|
|
return GuiInstancePropertyInfo::Array(TypeInfoRetriver<GuiCellOption>::CreateTypeInfo());
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
if (prop == _Rows)
|
|
{
|
|
auto indexColumns = arguments.Keys().IndexOf(_Columns);
|
|
if (indexColumns != -1)
|
|
{
|
|
auto& rows = arguments.GetByIndex(index);
|
|
auto& columns = arguments.GetByIndex(indexColumns);
|
|
|
|
{
|
|
auto refComposition = Ptr(new WfReferenceExpression);
|
|
refComposition->name.value = variableName.ToString();
|
|
|
|
auto refSetRowsAndColumns = Ptr(new WfMemberExpression);
|
|
refSetRowsAndColumns->parent = refComposition;
|
|
refSetRowsAndColumns->name.value = L"SetRowsAndColumns";
|
|
|
|
auto rowsExpr = Ptr(new WfIntegerExpression);
|
|
rowsExpr->value.value = itow(rows.Count());
|
|
|
|
auto columnsExpr = Ptr(new WfIntegerExpression);
|
|
columnsExpr->value.value = itow(columns.Count());
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refSetRowsAndColumns;
|
|
call->arguments.Add(rowsExpr);
|
|
call->arguments.Add(columnsExpr);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
|
|
for (vint i = 0; i < rows.Count(); i++)
|
|
{
|
|
auto refComposition = Ptr(new WfReferenceExpression);
|
|
refComposition->name.value = variableName.ToString();
|
|
|
|
auto refSetRowOption = Ptr(new WfMemberExpression);
|
|
refSetRowOption->parent = refComposition;
|
|
refSetRowOption->name.value = L"SetRowOption";
|
|
|
|
auto indexExpr = Ptr(new WfIntegerExpression);
|
|
indexExpr->value.value = itow(i);
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refSetRowOption;
|
|
call->arguments.Add(indexExpr);
|
|
call->arguments.Add(rows[i].expression);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
|
|
for (vint i = 0; i < columns.Count(); i++)
|
|
{
|
|
auto refComposition = Ptr(new WfReferenceExpression);
|
|
refComposition->name.value = variableName.ToString();
|
|
|
|
auto refSetColumnOption = Ptr(new WfMemberExpression);
|
|
refSetColumnOption->parent = refComposition;
|
|
refSetColumnOption->name.value = L"SetColumnOption";
|
|
|
|
auto indexExpr = Ptr(new WfIntegerExpression);
|
|
indexExpr->value.value = itow(i);
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refSetColumnOption;
|
|
call->arguments.Add(indexExpr);
|
|
call->arguments.Add(columns[i].expression);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiCellCompositionInstanceLoader
|
|
***********************************************************************/
|
|
|
|
class GuiCellCompositionInstanceLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
GlobalStringKey _Site;
|
|
|
|
public:
|
|
GuiCellCompositionInstanceLoader()
|
|
{
|
|
typeName = GlobalStringKey::Get(description::TypeInfo<GuiCellComposition>::content.typeName);
|
|
_Site = GlobalStringKey::Get(L"Site");
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
propertyNames.Add(_Site);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _Site)
|
|
{
|
|
return GuiInstancePropertyInfo::Assign(TypeInfoRetriver<SiteValue>::CreateTypeInfo());
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
if (prop == _Site)
|
|
{
|
|
SiteValue site;
|
|
{
|
|
auto siteExpr = arguments.GetByIndex(index)[0].expression;
|
|
if (auto inferExpr = siteExpr.Cast<WfInferExpression>())
|
|
{
|
|
if (auto ctorExpr = inferExpr->expression.Cast<WfConstructorExpression>())
|
|
{
|
|
auto st = description::GetTypeDescriptor<vint>()->GetSerializableType();
|
|
for (auto argument : ctorExpr->arguments)
|
|
{
|
|
if (auto keyExpr = argument->key.Cast<WfReferenceExpression>())
|
|
{
|
|
if (auto valueExpr = argument->value.Cast<WfIntegerExpression>())
|
|
{
|
|
Value value;
|
|
if (st->Deserialize(valueExpr->value.value, value))
|
|
{
|
|
vint propValue = UnboxValue<vint>(value);
|
|
if (keyExpr->name.value == L"row")
|
|
{
|
|
site.row = propValue;
|
|
}
|
|
else if (keyExpr->name.value == L"column")
|
|
{
|
|
site.column = propValue;
|
|
}
|
|
else if (keyExpr->name.value == L"rowSpan")
|
|
{
|
|
site.rowSpan = propValue;
|
|
}
|
|
else if (keyExpr->name.value == L"columnSpan")
|
|
{
|
|
site.columnSpan = propValue;
|
|
}
|
|
else
|
|
{
|
|
goto ILLEGAL_SITE_PROPERTY;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
goto ILLEGAL_SITE_PROPERTY;
|
|
}
|
|
goto FINISH_SITE_PROPERTY;
|
|
}
|
|
}
|
|
ILLEGAL_SITE_PROPERTY:
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, attPosition,
|
|
L"Precompile: The value of property \"Site\" of type \"" +
|
|
typeInfo.typeName.ToString() +
|
|
L"\" is not in a correct format: \"row:<integer> column:<integer> [rowSpan:<integer>] [columnSpan:<integer>]\"."));
|
|
continue;
|
|
}
|
|
FINISH_SITE_PROPERTY:;
|
|
|
|
{
|
|
auto refComposition = Ptr(new WfReferenceExpression);
|
|
refComposition->name.value = variableName.ToString();
|
|
|
|
auto refSetSite = Ptr(new WfMemberExpression);
|
|
refSetSite->parent = refComposition;
|
|
refSetSite->name.value = L"SetSite";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refSetSite;
|
|
|
|
{
|
|
auto arg = Ptr(new WfIntegerExpression);
|
|
arg->value.value = itow(site.row);
|
|
call->arguments.Add(arg);
|
|
}
|
|
{
|
|
auto arg = Ptr(new WfIntegerExpression);
|
|
arg->value.value = itow(site.column);
|
|
call->arguments.Add(arg);
|
|
}
|
|
{
|
|
auto arg = Ptr(new WfIntegerExpression);
|
|
arg->value.value = itow(site.rowSpan);
|
|
call->arguments.Add(arg);
|
|
}
|
|
{
|
|
auto arg = Ptr(new WfIntegerExpression);
|
|
arg->value.value = itow(site.columnSpan);
|
|
call->arguments.Add(arg);
|
|
}
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Initialization
|
|
***********************************************************************/
|
|
|
|
void LoadCompositions(IGuiInstanceLoaderManager* manager)
|
|
{
|
|
manager->SetLoader(Ptr(new GuiAxisInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiCompositionInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiTableCompositionInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiCellCompositionInstanceLoader));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\INSTANCELOADERS\GUIINSTANCELOADER_DOCUMENT.CPP
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
namespace instance_loaders
|
|
{
|
|
|
|
/***********************************************************************
|
|
GuiDocumentItemInstanceLoader
|
|
***********************************************************************/
|
|
|
|
class GuiDocumentItemInstanceLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
GlobalStringKey _Name;
|
|
|
|
public:
|
|
GuiDocumentItemInstanceLoader()
|
|
{
|
|
typeName = GlobalStringKey::Get(description::TypeInfo<GuiDocumentItem>::content.typeName);
|
|
_Name = GlobalStringKey::Get(L"Name");
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
void GetRequiredPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
propertyNames.Add(_Name);
|
|
}
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
propertyNames.Add(GlobalStringKey::Empty);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == GlobalStringKey::Empty)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Collection(nullptr);
|
|
info->acceptableTypes.Add(TypeInfoRetriver<GuiControl*>::CreateTypeInfo());
|
|
info->acceptableTypes.Add(TypeInfoRetriver<GuiGraphicsComposition*>::CreateTypeInfo());
|
|
return info;
|
|
}
|
|
else if (propertyInfo.propertyName == _Name)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<WString>::CreateTypeInfo());
|
|
info->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
return info;
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
|
|
bool CanCreate(const TypeInfo& typeInfo)override
|
|
{
|
|
return typeName == typeInfo.typeName;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> CreateInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos tagPosition, GuiResourceError::List& errors)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
vint indexName = arguments.Keys().IndexOf(_Name);
|
|
if (indexName != -1)
|
|
{
|
|
auto type = TypeInfoRetriver<Ptr<GuiDocumentItem>>::CreateTypeInfo();
|
|
auto createExpr = Ptr(new WfNewClassExpression);
|
|
createExpr->type = GetTypeFromTypeInfo(type.Obj());
|
|
createExpr->arguments.Add(arguments.GetByIndex(indexName)[0].expression);
|
|
|
|
auto refVariable = Ptr(new WfReferenceExpression);
|
|
refVariable->name.value = variableName.ToString();
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
assignExpr->first = refVariable;
|
|
assignExpr->second = createExpr;
|
|
|
|
auto assignStat = Ptr(new WfExpressionStatement);
|
|
assignStat->expression = assignExpr;
|
|
return assignStat;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
const auto& values = arguments.GetByIndex(index);
|
|
if (prop == GlobalStringKey::Empty)
|
|
{
|
|
auto value = values[0].expression;
|
|
auto td = values[0].typeInfo->GetTypeDescriptor();
|
|
|
|
Ptr<WfExpression> compositionExpr;
|
|
if (td->CanConvertTo(description::GetTypeDescriptor<GuiControl>()))
|
|
{
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = value;
|
|
member->name.value = L"BoundsComposition";
|
|
compositionExpr = member;
|
|
}
|
|
else if (td->CanConvertTo(description::GetTypeDescriptor<GuiGraphicsComposition>()))
|
|
{
|
|
compositionExpr = value;
|
|
}
|
|
|
|
if (compositionExpr)
|
|
{
|
|
auto refItem = Ptr(new WfReferenceExpression);
|
|
refItem->name.value = variableName.ToString();
|
|
|
|
auto refContainer = Ptr(new WfMemberExpression);
|
|
refContainer->parent = refItem;
|
|
refContainer->name.value = L"Container";
|
|
|
|
auto refAddChild = Ptr(new WfMemberExpression);
|
|
refAddChild->parent = refContainer;
|
|
refAddChild->name.value = L"AddChild";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddChild;
|
|
call->arguments.Add(compositionExpr);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiDocumentInstanceLoaderBase
|
|
***********************************************************************/
|
|
|
|
template<typename TBaseType>
|
|
class GuiDocumentInstanceLoaderBase : public TBaseType
|
|
{
|
|
private:
|
|
using TypeInfo = typename TBaseType::TypeInfo;
|
|
|
|
public:
|
|
using PropertyInfo = IGuiInstanceLoader::PropertyInfo;
|
|
using ArgumentMap = IGuiInstanceLoader::ArgumentMap;
|
|
|
|
GuiDocumentInstanceLoaderBase(const WString& _typeName, theme::ThemeName themeName)
|
|
:TBaseType(_typeName, themeName)
|
|
{
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
propertyNames.Add(GlobalStringKey::Empty);
|
|
TBaseType::GetPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == GlobalStringKey::Empty)
|
|
{
|
|
return GuiInstancePropertyInfo::CollectionWithParent(TypeInfoRetriver<Ptr<GuiDocumentItem>>::CreateTypeInfo());
|
|
}
|
|
return TBaseType::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
const auto& values = arguments.GetByIndex(index);
|
|
if (prop == GlobalStringKey::Empty)
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refAddDocumentItem = Ptr(new WfMemberExpression);
|
|
refAddDocumentItem->parent = refControl;
|
|
refAddDocumentItem->name.value = L"AddDocumentItem";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddDocumentItem;
|
|
call->arguments.Add(values[0].expression);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return TBaseType::AssignParameters(precompileContext, resolvingResult, typeInfo, variableName, arguments, attPosition, errors);
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiDocumentViewerInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiDocumentViewer>
|
|
class GuiDocumentViewerInstanceLoader : public GuiDocumentInstanceLoaderBase<BASE_TYPE>
|
|
{
|
|
public:
|
|
GuiDocumentViewerInstanceLoader()
|
|
:GuiDocumentInstanceLoaderBase<BASE_TYPE>(description::TypeInfo<GuiDocumentViewer>::content.typeName, theme::ThemeName::DocumentViewer)
|
|
{
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiDocumentLabelInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiDocumentLabel>
|
|
class GuiDocumentLabelInstanceLoader : public GuiDocumentInstanceLoaderBase<BASE_TYPE>
|
|
{
|
|
public:
|
|
GuiDocumentLabelInstanceLoader()
|
|
:GuiDocumentInstanceLoaderBase<BASE_TYPE>(description::TypeInfo<GuiDocumentLabel>::content.typeName, theme::ThemeName::DocumentLabel)
|
|
{
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
Initialization
|
|
***********************************************************************/
|
|
|
|
void LoadDocumentControls(IGuiInstanceLoaderManager* manager)
|
|
{
|
|
manager->SetLoader(Ptr(new GuiDocumentItemInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiDocumentViewerInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiDocumentLabelInstanceLoader));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\INSTANCELOADERS\GUIINSTANCELOADER_LIST.CPP
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
namespace instance_loaders
|
|
{
|
|
|
|
template<typename TItemTemplateStyle>
|
|
Ptr<WfStatement> CreateSetControlTemplateStyle(types::ResolvingResult& resolvingResult, GlobalStringKey variableName, Ptr<WfExpression> argument, const WString& propertyName)
|
|
{
|
|
auto createStyle = Ptr(new WfNewClassExpression);
|
|
createStyle->type = GetTypeFromTypeInfo(TypeInfoRetriver<Ptr<TItemTemplateStyle>>::CreateTypeInfo().Obj());
|
|
createStyle->arguments.Add(argument);
|
|
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refStyleProvider = Ptr(new WfMemberExpression);
|
|
refStyleProvider->parent = refControl;
|
|
refStyleProvider->name.value = propertyName;
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refStyleProvider;
|
|
assign->second = createStyle;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
return stat;
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiComboButtonInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiComboButton>
|
|
class GuiComboButtonInstanceLoader : public BASE_TYPE
|
|
{
|
|
protected:
|
|
GlobalStringKey _DropdownControl;
|
|
|
|
void AddAdditionalArguments(types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceError::List& errors, Ptr<WfNewClassExpression> createControl)override
|
|
{
|
|
vint indexListControl = arguments.Keys().IndexOf(_DropdownControl);
|
|
if (indexListControl != -1)
|
|
{
|
|
createControl->arguments.Add(arguments.GetByIndex(indexListControl)[0].expression);
|
|
}
|
|
}
|
|
public:
|
|
GuiComboButtonInstanceLoader()
|
|
:BASE_TYPE(L"presentation::controls::GuiComboButton", theme::ThemeName::ComboBox)
|
|
{
|
|
_DropdownControl = GlobalStringKey::Get(L"DropdownControl");
|
|
}
|
|
|
|
void GetRequiredPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
propertyNames.Add(_DropdownControl);
|
|
}
|
|
BASE_TYPE::GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
BASE_TYPE::GetPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _DropdownControl)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<GuiControl*>::CreateTypeInfo());
|
|
info->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
return info;
|
|
}
|
|
return BASE_TYPE::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiComboBoxInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiComboBoxListControl>
|
|
class GuiComboBoxInstanceLoader : public BASE_TYPE
|
|
{
|
|
protected:
|
|
GlobalStringKey _ListControl;
|
|
|
|
void AddAdditionalArguments(types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceError::List& errors, Ptr<WfNewClassExpression> createControl)override
|
|
{
|
|
vint indexListControl = arguments.Keys().IndexOf(_ListControl);
|
|
if (indexListControl != -1)
|
|
{
|
|
createControl->arguments.Add(arguments.GetByIndex(indexListControl)[0].expression);
|
|
}
|
|
}
|
|
public:
|
|
GuiComboBoxInstanceLoader()
|
|
:BASE_TYPE(L"presentation::controls::GuiComboBox", theme::ThemeName::ComboBox)
|
|
{
|
|
_ListControl = GlobalStringKey::Get(L"ListControl");
|
|
}
|
|
|
|
void GetRequiredPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
propertyNames.Add(_ListControl);
|
|
}
|
|
BASE_TYPE::GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
BASE_TYPE::GetPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _ListControl)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<GuiSelectableListControl*>::CreateTypeInfo());
|
|
info->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
return info;
|
|
}
|
|
return BASE_TYPE::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiTreeViewInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<TControl>
|
|
template<typename TControl>
|
|
class GuiTreeViewInstanceLoaderBase : public BASE_TYPE
|
|
{
|
|
protected:
|
|
bool bindable;
|
|
GlobalStringKey _Nodes;
|
|
|
|
public:
|
|
GuiTreeViewInstanceLoaderBase(bool _bindable)
|
|
:BASE_TYPE(description::TypeInfo<TControl>::content.typeName, theme::ThemeName::TreeView)
|
|
, bindable(_bindable)
|
|
{
|
|
_Nodes = GlobalStringKey::Get(L"Nodes");
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const typename BASE_TYPE::TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (!bindable)
|
|
{
|
|
propertyNames.Add(_Nodes);
|
|
}
|
|
BASE_TYPE::GetPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const typename BASE_TYPE::PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _Nodes)
|
|
{
|
|
if (!bindable)
|
|
{
|
|
return GuiInstancePropertyInfo::Collection(TypeInfoRetriver<Ptr<tree::MemoryNodeProvider>>::CreateTypeInfo());
|
|
}
|
|
}
|
|
return BASE_TYPE::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const typename BASE_TYPE::TypeInfo& typeInfo, GlobalStringKey variableName, typename BASE_TYPE::ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
if (prop == _Nodes)
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refNodes = Ptr(new WfMemberExpression);
|
|
refNodes->parent = refControl;
|
|
refNodes->name.value = L"Nodes";
|
|
|
|
auto refChildren = Ptr(new WfMemberExpression);
|
|
refChildren->parent = refNodes;
|
|
refChildren->name.value = L"Children";
|
|
|
|
auto refAdd = Ptr(new WfMemberExpression);
|
|
refAdd->parent = refChildren;
|
|
refAdd->name.value = L"Add";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAdd;
|
|
call->arguments.Add(arguments.GetByIndex(index)[0].expression);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return BASE_TYPE::AssignParameters(precompileContext, resolvingResult, typeInfo, variableName, arguments, attPosition, errors);
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
class GuiTreeViewInstanceLoader : public GuiTreeViewInstanceLoaderBase<GuiTreeView>
|
|
{
|
|
public:
|
|
GuiTreeViewInstanceLoader()
|
|
:GuiTreeViewInstanceLoaderBase<GuiTreeView>(false)
|
|
{
|
|
}
|
|
};
|
|
|
|
class GuiBindableTreeViewInstanceLoader : public GuiTreeViewInstanceLoaderBase<GuiBindableTreeView>
|
|
{
|
|
public:
|
|
GuiBindableTreeViewInstanceLoader()
|
|
:GuiTreeViewInstanceLoaderBase<GuiBindableTreeView>(true)
|
|
{
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiTreeNodeInstanceLoader
|
|
***********************************************************************/
|
|
|
|
class GuiTreeNodeInstanceLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
GlobalStringKey _Text, _Image, _Tag;
|
|
|
|
public:
|
|
GuiTreeNodeInstanceLoader()
|
|
:typeName(GlobalStringKey::Get(L"presentation::controls::tree::TreeNode"))
|
|
{
|
|
_Text = GlobalStringKey::Get(L"Text");
|
|
_Image = GlobalStringKey::Get(L"Image");
|
|
_Tag = GlobalStringKey::Get(L"Tag");
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
propertyNames.Add(_Text);
|
|
propertyNames.Add(_Image);
|
|
propertyNames.Add(_Tag);
|
|
propertyNames.Add(GlobalStringKey::Empty);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _Text)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<WString>::CreateTypeInfo());
|
|
info->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
info->bindability = GuiInstancePropertyInfo::Bindable;
|
|
return info;
|
|
}
|
|
else if (propertyInfo.propertyName == _Image)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<Ptr<GuiImageData>>::CreateTypeInfo());
|
|
info->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
info->bindability = GuiInstancePropertyInfo::Bindable;
|
|
return info;
|
|
}
|
|
else if (propertyInfo.propertyName == _Tag)
|
|
{
|
|
return GuiInstancePropertyInfo::Assign(TypeInfoRetriver<Value>::CreateTypeInfo());
|
|
}
|
|
else if (propertyInfo.propertyName == GlobalStringKey::Empty)
|
|
{
|
|
return GuiInstancePropertyInfo::Collection(TypeInfoRetriver<Ptr<tree::MemoryNodeProvider>>::CreateTypeInfo());
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
bool CanCreate(const TypeInfo& typeInfo)override
|
|
{
|
|
return typeInfo.typeName == GetTypeName();
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> CreateInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos tagPosition, GuiResourceError::List& errors)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
auto createItem = Ptr(new WfNewClassExpression);
|
|
createItem->type = GetTypeFromTypeInfo(TypeInfoRetriver<Ptr<tree::TreeViewItem>>::CreateTypeInfo().Obj());
|
|
|
|
vint imageIndex = arguments.Keys().IndexOf(_Image);
|
|
vint textIndex = arguments.Keys().IndexOf(_Text);
|
|
|
|
if (imageIndex != -1 || textIndex != -1)
|
|
{
|
|
if (imageIndex == -1)
|
|
{
|
|
auto nullExpr = Ptr(new WfLiteralExpression);
|
|
nullExpr->value = WfLiteralValue::Null;
|
|
createItem->arguments.Add(nullExpr);
|
|
}
|
|
else
|
|
{
|
|
createItem->arguments.Add(arguments.GetByIndex(imageIndex)[0].expression);
|
|
}
|
|
|
|
if (textIndex == -1)
|
|
{
|
|
createItem->arguments.Add(Ptr(new WfStringExpression));
|
|
}
|
|
else
|
|
{
|
|
createItem->arguments.Add(arguments.GetByIndex(textIndex)[0].expression);
|
|
}
|
|
}
|
|
|
|
auto createNode = Ptr(new WfNewClassExpression);
|
|
createNode->type = GetTypeFromTypeInfo(TypeInfoRetriver<Ptr<tree::MemoryNodeProvider>>::CreateTypeInfo().Obj());
|
|
createNode->arguments.Add(createItem);
|
|
|
|
auto refNode = Ptr(new WfReferenceExpression);
|
|
refNode->name.value = variableName.ToString();
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refNode;
|
|
assign->second = createNode;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
return stat;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
if (prop == GlobalStringKey::Empty)
|
|
{
|
|
auto refNode = Ptr(new WfReferenceExpression);
|
|
refNode->name.value = variableName.ToString();
|
|
|
|
auto refChildren = Ptr(new WfMemberExpression);
|
|
refChildren->parent = refNode;
|
|
refChildren->name.value = L"Children";
|
|
|
|
auto refAdd = Ptr(new WfMemberExpression);
|
|
refAdd->parent = refChildren;
|
|
refAdd->name.value = L"Add";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAdd;
|
|
call->arguments.Add(arguments.GetByIndex(index)[0].expression);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
else if (prop == _Tag)
|
|
{
|
|
{
|
|
auto refNode = Ptr(new WfReferenceExpression);
|
|
refNode->name.value = variableName.ToString();
|
|
|
|
auto refData = Ptr(new WfMemberExpression);
|
|
refData->parent = refNode;
|
|
refData->name.value = L"Data";
|
|
|
|
auto castExpr = Ptr(new WfTypeCastingExpression);
|
|
castExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
castExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<Ptr<tree::TreeViewItem>>::CreateTypeInfo().Obj());
|
|
castExpr->expression = refData;
|
|
|
|
auto refProp = Ptr(new WfMemberExpression);
|
|
refProp->parent = castExpr;
|
|
refProp->name.value = L"tag";
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refProp;
|
|
assign->second = arguments.GetByIndex(index)[0].expression;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
block->statements.Add(stat);
|
|
}
|
|
|
|
if (prop != _Tag)
|
|
{
|
|
auto refNode = Ptr(new WfReferenceExpression);
|
|
refNode->name.value = variableName.ToString();
|
|
|
|
auto refNotifyDataModified = Ptr(new WfMemberExpression);
|
|
refNotifyDataModified->parent = refNode;
|
|
refNotifyDataModified->name.value = L"NotifyDataModified";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refNotifyDataModified;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiBindableDataGridInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiBindableDataGrid>
|
|
class GuiBindableDataGridInstanceLoader : public BASE_TYPE
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
|
|
public:
|
|
GuiBindableDataGridInstanceLoader()
|
|
:BASE_TYPE(description::TypeInfo<GuiBindableDataGrid>::content.typeName, theme::ThemeName::ListView)
|
|
{
|
|
typeName = GlobalStringKey::Get(description::TypeInfo<GuiBindableDataGrid>::content.typeName);
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
Initialization
|
|
***********************************************************************/
|
|
|
|
void LoadListControls(IGuiInstanceLoaderManager* manager)
|
|
{
|
|
manager->CreateVirtualType(
|
|
GlobalStringKey::Get(description::TypeInfo<GuiComboBoxListControl>::content.typeName),
|
|
Ptr(new GuiComboBoxInstanceLoader)
|
|
);
|
|
|
|
manager->SetLoader(Ptr(new GuiComboButtonInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiTreeViewInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiBindableTreeViewInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiBindableDataGridInstanceLoader));
|
|
|
|
manager->CreateVirtualType(
|
|
GlobalStringKey::Get(description::TypeInfo<tree::MemoryNodeProvider>::content.typeName),
|
|
Ptr(new GuiTreeNodeInstanceLoader)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\INSTANCELOADERS\GUIINSTANCELOADER_PLUGIN.CPP
|
|
***********************************************************************/
|
|
/*
|
|
GuiInstanceLoader_Plugin.cpp
|
|
GuiControl
|
|
default: GuiControl*, GuiGraphicsComposition*
|
|
GuiInstanceRootObject
|
|
default: GuiComponent*
|
|
GuiInstanceLoader_TemplateControl.h
|
|
GuiControl
|
|
GuiInstanceLoader_Compositions.cpp
|
|
GuiAxis
|
|
ctor: AxisDirection
|
|
GuiComposition
|
|
default: GuiControl*, GuiGraphicsComposition*, Ptr<IGuiGraphicsElement>
|
|
GuiTableComposition
|
|
Rows, Columns: array(GuiCellOption)
|
|
GuiCellComposition
|
|
Site: SiteValue
|
|
GuiInstanceLoader_Document.cpp
|
|
GuiDocumentItem
|
|
default: GuiControl*, GuiGraphicsComposition*
|
|
GuiDocumentViewer, GuiDocumentLable
|
|
default: Ptr<GuiDocumentItem>
|
|
GuiInstanceLoader_List.cpp
|
|
GuiComboBox
|
|
ctor: _ListControl(GuiListControl*)
|
|
GuiTreeView, GuiBindableTreeView
|
|
Nodes: array(Ptr<tree::MemoryNodeProvider>)
|
|
tree::TreeNode
|
|
ctor: Text, Image
|
|
Tag
|
|
GuiInstanceLoader_Templates.cpp
|
|
GuiCommonDatePickerLook
|
|
ctor: BackgroundColor, PrimaryTextColor, SecondaryTextColor
|
|
GuiCommonScrollViewLook
|
|
ctor: DefaultScrollSize
|
|
GuiInstanceLoader_Toolstrip.cpp
|
|
GuiToolstripMenu, GuiToolstripMenuBar, GuiToolstripToolBar, GuiBindableRibbonGalleryMenu
|
|
default: collection(GuiControl*)
|
|
GuiToolstripButton
|
|
SubMenu-set: GuiToolstripMenu*
|
|
GuiRibbonButtons
|
|
ctor: MaxSize, MinSize
|
|
*/
|
|
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
namespace instance_loaders
|
|
{
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
/***********************************************************************
|
|
GuiControlInstanceLoader
|
|
***********************************************************************/
|
|
|
|
class GuiControlInstanceLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
|
|
public:
|
|
GuiControlInstanceLoader()
|
|
{
|
|
typeName = GlobalStringKey::Get(description::TypeInfo<GuiControl>::content.typeName);
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
propertyNames.Add(GlobalStringKey::Empty);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == GlobalStringKey::Empty)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Collection(nullptr);
|
|
info->acceptableTypes.Add(TypeInfoRetriver<GuiControl*>::CreateTypeInfo());
|
|
info->acceptableTypes.Add(TypeInfoRetriver<GuiGraphicsComposition*>::CreateTypeInfo());
|
|
if (propertyInfo.typeInfo.typeInfo->GetTypeDescriptor()->CanConvertTo(description::GetTypeDescriptor<GuiInstanceRootObject>()))
|
|
{
|
|
info->acceptableTypes.Add(TypeInfoRetriver<GuiComponent*>::CreateTypeInfo());
|
|
}
|
|
return info;
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
const auto& values = arguments.GetByIndex(index);
|
|
if (prop == GlobalStringKey::Empty)
|
|
{
|
|
auto value = values[0].expression;
|
|
auto td = values[0].typeInfo->GetTypeDescriptor();
|
|
|
|
Ptr<WfExpression> expr;
|
|
if (td->CanConvertTo(description::GetTypeDescriptor<GuiComponent>()))
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refAddComponent = Ptr(new WfMemberExpression);
|
|
refAddComponent->parent = refControl;
|
|
refAddComponent->name.value = L"AddComponent";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddComponent;
|
|
call->arguments.Add(value);
|
|
|
|
expr = call;
|
|
}
|
|
else if (td->CanConvertTo(description::GetTypeDescriptor<GuiControlHost>()))
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refAddControlHostComponent = Ptr(new WfMemberExpression);
|
|
refAddControlHostComponent->parent = refControl;
|
|
refAddControlHostComponent->name.value = L"AddControlHostComponent";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddControlHostComponent;
|
|
call->arguments.Add(value);
|
|
|
|
expr = call;
|
|
}
|
|
else if (td->CanConvertTo(description::GetTypeDescriptor<GuiControl>()))
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refAddChild = Ptr(new WfMemberExpression);
|
|
refAddChild->parent = refControl;
|
|
refAddChild->name.value = L"AddChild";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddChild;
|
|
call->arguments.Add(value);
|
|
|
|
expr = call;
|
|
}
|
|
else if (td->CanConvertTo(description::GetTypeDescriptor<GuiGraphicsComposition>()))
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refContainerComposition = Ptr(new WfMemberExpression);
|
|
refContainerComposition->parent = refControl;
|
|
refContainerComposition->name.value = L"ContainerComposition";
|
|
|
|
auto refAddChild = Ptr(new WfMemberExpression);
|
|
refAddChild->parent = refContainerComposition;
|
|
refAddChild->name.value = L"AddChild";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAddChild;
|
|
call->arguments.Add(value);
|
|
|
|
expr = call;
|
|
}
|
|
|
|
if (expr)
|
|
{
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = expr;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
GuiPredefinedInstanceLoadersPlugin
|
|
***********************************************************************/
|
|
|
|
void InitializeTrackerProgressBar(const WString& variableName, Ptr<WfBlockStatement> block)
|
|
{
|
|
auto refVariable = Ptr(new WfReferenceExpression);
|
|
refVariable->name.value = variableName;
|
|
|
|
auto refSetPageSize = Ptr(new WfMemberExpression);
|
|
refSetPageSize->parent = refVariable;
|
|
refSetPageSize->name.value = L"SetPageSize";
|
|
|
|
auto refZero = Ptr(new WfIntegerExpression);
|
|
refZero->value.value = L"0";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refSetPageSize;
|
|
call->arguments.Add(refZero);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
block->statements.Add(stat);
|
|
}
|
|
|
|
extern void LoadToolstripControls(IGuiInstanceLoaderManager* manager);
|
|
extern void LoadListControls(IGuiInstanceLoaderManager* manager);
|
|
extern void LoadDocumentControls(IGuiInstanceLoaderManager* manager);
|
|
extern void LoadCompositions(IGuiInstanceLoaderManager* manager);
|
|
extern void LoadTemplates(IGuiInstanceLoaderManager* manager);
|
|
|
|
class GuiPredefinedInstanceLoadersPlugin : public Object, public IGuiPlugin
|
|
{
|
|
public:
|
|
|
|
GUI_PLUGIN_NAME(GacUI_Instance_TypeLoaders)
|
|
{
|
|
GUI_PLUGIN_DEPEND(GacUI_Res_ResourceResolver);
|
|
GUI_PLUGIN_DEPEND(GacUI_Instance);
|
|
GUI_PLUGIN_DEPEND(GacUI_Instance_Reflection);
|
|
}
|
|
|
|
void Load()override
|
|
{
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
IGuiInstanceLoaderManager* manager=GetInstanceLoaderManager();
|
|
|
|
#define ADD_TEMPLATE_CONTROL(TYPENAME, THEME_NAME)\
|
|
manager->SetLoader(\
|
|
Ptr(new GuiTemplateControlInstanceLoader<TYPENAME>(\
|
|
L"presentation::controls::" L ## #TYPENAME,\
|
|
theme::ThemeName::THEME_NAME\
|
|
)\
|
|
))
|
|
|
|
#define ADD_VIRTUAL_CONTROL(VIRTUALTYPENAME, TYPENAME, THEME_NAME)\
|
|
manager->CreateVirtualType(GlobalStringKey::Get(description::TypeInfo<TYPENAME>::content.typeName),\
|
|
Ptr(new GuiTemplateControlInstanceLoader<TYPENAME>(\
|
|
L"presentation::controls::Gui" L ## #VIRTUALTYPENAME,\
|
|
theme::ThemeName::THEME_NAME\
|
|
)\
|
|
))
|
|
|
|
#define ADD_VIRTUAL_CONTROL_F(VIRTUALTYPENAME, TYPENAME, THEME_NAME, INIT_FUNCTION)\
|
|
manager->CreateVirtualType(GlobalStringKey::Get(description::TypeInfo<TYPENAME>::content.typeName),\
|
|
Ptr(new GuiTemplateControlInstanceLoader<TYPENAME>(\
|
|
L"presentation::controls::Gui" L ## #VIRTUALTYPENAME,\
|
|
theme::ThemeName::THEME_NAME,\
|
|
nullptr,\
|
|
INIT_FUNCTION\
|
|
)\
|
|
))
|
|
|
|
manager->SetLoader(Ptr(new GuiControlInstanceLoader));
|
|
|
|
/* REAL-CONTROL-TYPE THEME-NAME */
|
|
ADD_TEMPLATE_CONTROL ( GuiCustomControl, CustomControl );
|
|
ADD_TEMPLATE_CONTROL ( GuiLabel, Label );
|
|
ADD_TEMPLATE_CONTROL ( GuiButton, Button );
|
|
ADD_TEMPLATE_CONTROL ( GuiTabPage, CustomControl );
|
|
ADD_TEMPLATE_CONTROL ( GuiTab, Tab );
|
|
ADD_TEMPLATE_CONTROL ( GuiScrollContainer, ScrollView );
|
|
ADD_TEMPLATE_CONTROL ( GuiWindow, Window );
|
|
ADD_TEMPLATE_CONTROL ( GuiTextList, TextList );
|
|
ADD_TEMPLATE_CONTROL ( GuiBindableTextList, TextList );
|
|
ADD_TEMPLATE_CONTROL ( GuiListView, ListView );
|
|
ADD_TEMPLATE_CONTROL ( GuiBindableListView, ListView );
|
|
ADD_TEMPLATE_CONTROL ( GuiMultilineTextBox, MultilineTextBox );
|
|
ADD_TEMPLATE_CONTROL ( GuiSinglelineTextBox, SinglelineTextBox );
|
|
ADD_TEMPLATE_CONTROL ( GuiDatePicker, DatePicker );
|
|
ADD_TEMPLATE_CONTROL ( GuiDateComboBox, DateComboBox );
|
|
ADD_TEMPLATE_CONTROL ( GuiRibbonTab, RibbonTab );
|
|
ADD_TEMPLATE_CONTROL ( GuiRibbonTabPage, CustomControl );
|
|
ADD_TEMPLATE_CONTROL ( GuiRibbonGroup, RibbonGroup );
|
|
ADD_TEMPLATE_CONTROL ( GuiRibbonIconLabel, RibbonIconLabel );
|
|
ADD_TEMPLATE_CONTROL ( GuiRibbonToolstrips, RibbonToolstrips );
|
|
ADD_TEMPLATE_CONTROL ( GuiRibbonGallery, RibbonGallery );
|
|
ADD_TEMPLATE_CONTROL ( GuiBindableRibbonGalleryList, RibbonGalleryList );
|
|
|
|
/* VIRTUAL-CONTROL-TYPE REAL-CONTROL-TYPE THEME-NAME */
|
|
ADD_VIRTUAL_CONTROL (GroupBox, GuiControl, GroupBox );
|
|
ADD_VIRTUAL_CONTROL (MenuSplitter, GuiControl, MenuSplitter );
|
|
ADD_VIRTUAL_CONTROL (MenuBarButton, GuiToolstripButton, MenuBarButton );
|
|
ADD_VIRTUAL_CONTROL (MenuItemButton, GuiToolstripButton, MenuItemButton );
|
|
ADD_VIRTUAL_CONTROL (ToolstripDropdownButton, GuiToolstripButton, ToolstripDropdownButton );
|
|
ADD_VIRTUAL_CONTROL (ToolstripSplitButton, GuiToolstripButton, ToolstripSplitButton );
|
|
ADD_VIRTUAL_CONTROL (ToolstripSplitter, GuiControl, ToolstripSplitter );
|
|
ADD_VIRTUAL_CONTROL (RibbonSmallButton, GuiToolstripButton, RibbonSmallButton );
|
|
ADD_VIRTUAL_CONTROL (RibbonSmallDropdownButton, GuiToolstripButton, RibbonSmallDropdownButton );
|
|
ADD_VIRTUAL_CONTROL (RibbonSmallSplitButton, GuiToolstripButton, RibbonSmallSplitButton );
|
|
ADD_VIRTUAL_CONTROL (RibbonLargeButton, GuiToolstripButton, RibbonLargeButton );
|
|
ADD_VIRTUAL_CONTROL (RibbonLargeDropdownButton, GuiToolstripButton, RibbonLargeDropdownButton );
|
|
ADD_VIRTUAL_CONTROL (RibbonLargeSplitButton, GuiToolstripButton, RibbonLargeSplitButton );
|
|
ADD_VIRTUAL_CONTROL (RibbonSmallIconLabel, GuiRibbonIconLabel, RibbonSmallIconLabel );
|
|
ADD_VIRTUAL_CONTROL (RibbonSplitter, GuiControl, RibbonSplitter );
|
|
ADD_VIRTUAL_CONTROL (RibbonToolstripHeader, GuiControl, RibbonToolstripHeader );
|
|
ADD_VIRTUAL_CONTROL (CheckBox, GuiSelectableButton, CheckBox );
|
|
ADD_VIRTUAL_CONTROL (RadioButton, GuiSelectableButton, RadioButton );
|
|
ADD_VIRTUAL_CONTROL (HScroll, GuiScroll, HScroll );
|
|
ADD_VIRTUAL_CONTROL (VScroll, GuiScroll, VScroll );
|
|
ADD_VIRTUAL_CONTROL (DocumentTextBox, GuiDocumentLabel, DocumentTextBox );
|
|
ADD_VIRTUAL_CONTROL_F (HTracker, GuiScroll, HTracker, InitializeTrackerProgressBar);
|
|
ADD_VIRTUAL_CONTROL_F (VTracker, GuiScroll, VTracker, InitializeTrackerProgressBar);
|
|
ADD_VIRTUAL_CONTROL_F (ProgressBar, GuiScroll, ProgressBar, InitializeTrackerProgressBar);
|
|
|
|
LoadToolstripControls(manager);
|
|
LoadListControls(manager);
|
|
LoadDocumentControls(manager);
|
|
LoadCompositions(manager);
|
|
LoadTemplates(manager);
|
|
|
|
#undef ADD_TEMPLATE_CONTROL
|
|
#undef ADD_VIRTUAL_CONTROL
|
|
#undef ADD_VIRTUAL_CONTROL_F
|
|
#endif
|
|
}
|
|
|
|
void Unload()override
|
|
{
|
|
}
|
|
};
|
|
GUI_REGISTER_PLUGIN(GuiPredefinedInstanceLoadersPlugin)
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\INSTANCELOADERS\GUIINSTANCELOADER_TEMPLATES.CPP
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
namespace instance_loaders
|
|
{
|
|
|
|
/***********************************************************************
|
|
GuiCommonDatePickerLookLoader
|
|
***********************************************************************/
|
|
|
|
class GuiCommonDatePickerLookLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
GlobalStringKey _BackgroundColor;
|
|
GlobalStringKey _PrimaryTextColor;
|
|
GlobalStringKey _SecondaryTextColor;
|
|
|
|
public:
|
|
GuiCommonDatePickerLookLoader()
|
|
{
|
|
typeName = GlobalStringKey::Get(description::TypeInfo<GuiCommonDatePickerLook>::content.typeName);
|
|
_BackgroundColor = GlobalStringKey::Get(L"BackgroundColor");
|
|
_PrimaryTextColor = GlobalStringKey::Get(L"PrimaryTextColor");
|
|
_SecondaryTextColor = GlobalStringKey::Get(L"SecondaryTextColor");
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
void GetRequiredPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
propertyNames.Add(_BackgroundColor);
|
|
propertyNames.Add(_PrimaryTextColor);
|
|
propertyNames.Add(_SecondaryTextColor);
|
|
}
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _BackgroundColor || propertyInfo.propertyName == _PrimaryTextColor || propertyInfo.propertyName == _SecondaryTextColor)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<Color>::CreateTypeInfo());
|
|
info->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
return info;
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
bool CanCreate(const TypeInfo& typeInfo)override
|
|
{
|
|
return typeInfo.typeName == typeName;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> CreateInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos tagPosition, GuiResourceError::List& errors)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
vint indexBackgroundColor = arguments.Keys().IndexOf(_BackgroundColor);
|
|
vint indexPrimaryTextColor = arguments.Keys().IndexOf(_PrimaryTextColor);
|
|
vint indexSecondaryTextColor = arguments.Keys().IndexOf(_SecondaryTextColor);
|
|
if (indexBackgroundColor != -1 && indexPrimaryTextColor != -1 && indexSecondaryTextColor != -1)
|
|
{
|
|
auto type = TypeInfoRetriver<GuiCommonDatePickerLook*>::CreateTypeInfo();
|
|
auto createExpr = Ptr(new WfNewClassExpression);
|
|
createExpr->type = GetTypeFromTypeInfo(type.Obj());
|
|
createExpr->arguments.Add(arguments.GetByIndex(indexBackgroundColor)[0].expression);
|
|
createExpr->arguments.Add(arguments.GetByIndex(indexPrimaryTextColor)[0].expression);
|
|
createExpr->arguments.Add(arguments.GetByIndex(indexSecondaryTextColor)[0].expression);
|
|
|
|
auto refVariable = Ptr(new WfReferenceExpression);
|
|
refVariable->name.value = variableName.ToString();
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
assignExpr->first = refVariable;
|
|
assignExpr->second = createExpr;
|
|
|
|
auto assignStat = Ptr(new WfExpressionStatement);
|
|
assignStat->expression = assignExpr;
|
|
return assignStat;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiCommonScrollViewLookLoader
|
|
***********************************************************************/
|
|
|
|
class GuiCommonScrollViewLookLoader : public Object, public IGuiInstanceLoader
|
|
{
|
|
protected:
|
|
GlobalStringKey typeName;
|
|
GlobalStringKey _DefaultScrollSize;
|
|
|
|
public:
|
|
GuiCommonScrollViewLookLoader()
|
|
{
|
|
typeName = GlobalStringKey::Get(description::TypeInfo<GuiCommonScrollViewLook>::content.typeName);
|
|
_DefaultScrollSize = GlobalStringKey::Get(L"DefaultScrollSize");
|
|
}
|
|
|
|
GlobalStringKey GetTypeName()override
|
|
{
|
|
return typeName;
|
|
}
|
|
|
|
void GetRequiredPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
propertyNames.Add(_DefaultScrollSize);
|
|
}
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _DefaultScrollSize)
|
|
{
|
|
Ptr<GuiInstancePropertyInfo> info;
|
|
switch (precompileContext.targetCpuArchitecture)
|
|
{
|
|
case GuiResourceCpuArchitecture::x86:
|
|
info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<vint32_t>::CreateTypeInfo());
|
|
break;
|
|
case GuiResourceCpuArchitecture::x64:
|
|
info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<vint64_t>::CreateTypeInfo());
|
|
break;
|
|
default:
|
|
CHECK_FAIL(L"The target CPU architecture is unspecified.");
|
|
}
|
|
info->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
return info;
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
bool CanCreate(const TypeInfo& typeInfo)override
|
|
{
|
|
return typeInfo.typeName == typeName;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> CreateInstance(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos tagPosition, GuiResourceError::List& errors)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
vint indexDefaultScrollSize = arguments.Keys().IndexOf(_DefaultScrollSize);
|
|
if (indexDefaultScrollSize != -1)
|
|
{
|
|
auto type = TypeInfoRetriver<GuiCommonScrollViewLook*>::CreateTypeInfo();
|
|
auto createExpr = Ptr(new WfNewClassExpression);
|
|
createExpr->type = GetTypeFromTypeInfo(type.Obj());
|
|
createExpr->arguments.Add(arguments.GetByIndex(indexDefaultScrollSize)[0].expression);
|
|
|
|
auto refVariable = Ptr(new WfReferenceExpression);
|
|
refVariable->name.value = variableName.ToString();
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
assignExpr->first = refVariable;
|
|
assignExpr->second = createExpr;
|
|
|
|
auto assignStat = Ptr(new WfExpressionStatement);
|
|
assignStat->expression = assignExpr;
|
|
return assignStat;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Initialization
|
|
***********************************************************************/
|
|
|
|
void LoadTemplates(IGuiInstanceLoaderManager* manager)
|
|
{
|
|
manager->SetLoader(Ptr(new GuiCommonDatePickerLookLoader));
|
|
manager->SetLoader(Ptr(new GuiCommonScrollViewLookLoader));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\INSTANCELOADERS\GUIINSTANCELOADER_TOOLSTRIP.CPP
|
|
***********************************************************************/
|
|
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
namespace instance_loaders
|
|
{
|
|
Ptr<workflow::WfStatement> AddControlToToolstrip(GlobalStringKey variableName, IGuiInstanceLoader::ArgumentMap& arguments, GuiResourceError::List& errors)
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
for (auto [prop, index] : indexed(arguments.Keys()))
|
|
{
|
|
const auto& values = arguments.GetByIndex(index);
|
|
if (prop == GlobalStringKey::Empty)
|
|
{
|
|
auto value = values[0].expression;
|
|
auto td = values[0].typeInfo->GetTypeDescriptor();
|
|
|
|
Ptr<WfExpression> expr;
|
|
if (td->CanConvertTo(description::GetTypeDescriptor<GuiControl>()))
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refToolstripItems = Ptr(new WfMemberExpression);
|
|
refToolstripItems->parent = refControl;
|
|
refToolstripItems->name.value = L"ToolstripItems";
|
|
|
|
auto refAdd = Ptr(new WfMemberExpression);
|
|
refAdd->parent = refToolstripItems;
|
|
refAdd->name.value = L"Add";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refAdd;
|
|
call->arguments.Add(value);
|
|
|
|
expr = call;
|
|
}
|
|
|
|
if (expr)
|
|
{
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = expr;
|
|
block->statements.Add(stat);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (block->statements.Count() > 0)
|
|
{
|
|
return block;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiToolstripInstanceLoaderBase
|
|
***********************************************************************/
|
|
|
|
template<typename TBaseType>
|
|
class GuiToolstripInstanceLoaderBase : public TBaseType
|
|
{
|
|
private:
|
|
using TypeInfo = typename TBaseType::TypeInfo;
|
|
|
|
public:
|
|
using ArgumentMap = IGuiInstanceLoader::ArgumentMap;
|
|
using PropertyInfo = IGuiInstanceLoader::PropertyInfo;
|
|
|
|
GuiToolstripInstanceLoaderBase(const WString& _typeName, theme::ThemeName themeName, Ptr<WfExpression>(*_argumentFunction)(ArgumentMap&))
|
|
:TBaseType(_typeName, themeName, _argumentFunction)
|
|
{
|
|
}
|
|
|
|
GuiToolstripInstanceLoaderBase(const WString& _typeName, theme::ThemeName themeName)
|
|
:TBaseType(_typeName, themeName)
|
|
{
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
propertyNames.Add(GlobalStringKey::Empty);
|
|
TBaseType::GetPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == GlobalStringKey::Empty)
|
|
{
|
|
return GuiInstancePropertyInfo::CollectionWithParent(TypeInfoRetriver<GuiControl*>::CreateTypeInfo());
|
|
}
|
|
return TBaseType::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> AssignParameters(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
if (auto statement = AddControlToToolstrip(variableName, arguments, errors))
|
|
{
|
|
return statement;
|
|
}
|
|
else
|
|
{
|
|
return TBaseType::AssignParameters(precompileContext, resolvingResult, typeInfo, variableName, arguments, attPosition, errors);
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
GuiToolstripMenuInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiToolstripMenu>
|
|
class GuiToolstripMenuInstanceLoader : public GuiToolstripInstanceLoaderBase<BASE_TYPE>
|
|
{
|
|
public:
|
|
static Ptr<WfExpression> ArgumentFunction(ArgumentMap&)
|
|
{
|
|
auto expr = Ptr(new WfLiteralExpression);
|
|
expr->value = WfLiteralValue::Null;
|
|
return expr;
|
|
}
|
|
public:
|
|
GuiToolstripMenuInstanceLoader()
|
|
:GuiToolstripInstanceLoaderBase<BASE_TYPE>(description::TypeInfo<GuiToolstripMenu>::content.typeName, theme::ThemeName::Menu, ArgumentFunction)
|
|
{
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiToolstripMenuBarInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiToolstripMenuBar>
|
|
class GuiToolstripMenuBarInstanceLoader : public GuiToolstripInstanceLoaderBase<BASE_TYPE>
|
|
{
|
|
public:
|
|
GuiToolstripMenuBarInstanceLoader()
|
|
:GuiToolstripInstanceLoaderBase<BASE_TYPE>(description::TypeInfo<GuiToolstripMenuBar>::content.typeName, theme::ThemeName::MenuBar)
|
|
{
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiToolstripToolBarInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiToolstripToolBar>
|
|
class GuiToolstripToolBarInstanceLoader : public GuiToolstripInstanceLoaderBase<BASE_TYPE>
|
|
{
|
|
public:
|
|
GuiToolstripToolBarInstanceLoader()
|
|
:GuiToolstripInstanceLoaderBase<BASE_TYPE>(description::TypeInfo<GuiToolstripToolBar>::content.typeName, theme::ThemeName::ToolstripToolBar)
|
|
{
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiToolstripGroupContainerInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiToolstripGroupContainer>
|
|
class GuiToolstripGroupContainerInstanceLoader : public GuiToolstripInstanceLoaderBase<BASE_TYPE>
|
|
{
|
|
public:
|
|
GuiToolstripGroupContainerInstanceLoader()
|
|
:GuiToolstripInstanceLoaderBase<BASE_TYPE>(description::TypeInfo<GuiToolstripGroupContainer>::content.typeName, theme::ThemeName::CustomControl)
|
|
{
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiToolstripGroupInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiToolstripGroup>
|
|
class GuiToolstripGroupInstanceLoader : public GuiToolstripInstanceLoaderBase<BASE_TYPE>
|
|
{
|
|
public:
|
|
GuiToolstripGroupInstanceLoader()
|
|
:GuiToolstripInstanceLoaderBase<BASE_TYPE>(description::TypeInfo<GuiToolstripGroup>::content.typeName, theme::ThemeName::CustomControl)
|
|
{
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiToolstripButtonInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiToolstripButton>
|
|
class GuiToolstripButtonInstanceLoader : public BASE_TYPE
|
|
{
|
|
protected:
|
|
GlobalStringKey _SubMenu;
|
|
|
|
public:
|
|
GuiToolstripButtonInstanceLoader()
|
|
:BASE_TYPE(description::TypeInfo<GuiToolstripButton>::content.typeName, theme::ThemeName::ToolstripButton)
|
|
{
|
|
_SubMenu = GlobalStringKey::Get(L"SubMenu");
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
propertyNames.Add(_SubMenu);
|
|
BASE_TYPE::GetPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _SubMenu)
|
|
{
|
|
return GuiInstancePropertyInfo::Set(TypeInfoRetriver<GuiToolstripMenu*>::CreateTypeInfo());
|
|
}
|
|
return BASE_TYPE::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> GetParameter(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, const PropertyInfo& propertyInfo, GlobalStringKey variableName, GuiResourceTextPos attPosition, GuiResourceError::List& errors)override
|
|
{
|
|
if (propertyInfo.propertyName == _SubMenu)
|
|
{
|
|
auto refControl = Ptr(new WfReferenceExpression);
|
|
refControl->name.value = variableName.ToString();
|
|
|
|
auto refEnsureToolstripSubMenu = Ptr(new WfMemberExpression);
|
|
refEnsureToolstripSubMenu->parent = refControl;
|
|
refEnsureToolstripSubMenu->name.value = L"EnsureToolstripSubMenu";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = refEnsureToolstripSubMenu;
|
|
|
|
return call;
|
|
}
|
|
return BASE_TYPE::GetParameter(precompileContext, resolvingResult, propertyInfo, variableName, attPosition, errors);
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiRibbonToolstripMenuInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiRibbonToolstripMenu>
|
|
class GuiRibbonToolstripMenuInstanceLoader : public GuiToolstripInstanceLoaderBase<BASE_TYPE>
|
|
{
|
|
public:
|
|
static Ptr<WfExpression> ArgumentFunction(ArgumentMap&)
|
|
{
|
|
auto expr = Ptr(new WfLiteralExpression);
|
|
expr->value = WfLiteralValue::Null;
|
|
return expr;
|
|
}
|
|
public:
|
|
GuiRibbonToolstripMenuInstanceLoader()
|
|
:GuiToolstripInstanceLoaderBase<BASE_TYPE>(description::TypeInfo<GuiRibbonToolstripMenu>::content.typeName, theme::ThemeName::RibbonToolstripMenu, ArgumentFunction)
|
|
{
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
GuiRibbonButtonsInstanceLoader
|
|
***********************************************************************/
|
|
|
|
#define BASE_TYPE GuiTemplateControlInstanceLoader<GuiRibbonButtons>
|
|
class GuiRibbonButtonsInstanceLoader : public BASE_TYPE
|
|
{
|
|
protected:
|
|
GlobalStringKey _MaxSize;
|
|
GlobalStringKey _MinSize;
|
|
|
|
void AddAdditionalArguments(types::ResolvingResult& resolvingResult, const TypeInfo& typeInfo, GlobalStringKey variableName, ArgumentMap& arguments, GuiResourceError::List& errors, Ptr<WfNewClassExpression> createControl)override
|
|
{
|
|
vint indexMaxSize = arguments.Keys().IndexOf(_MaxSize);
|
|
vint indexMinSize = arguments.Keys().IndexOf(_MinSize);
|
|
if (indexMaxSize != -1 && indexMinSize != -1)
|
|
{
|
|
createControl->arguments.Add(arguments.GetByIndex(indexMaxSize)[0].expression);
|
|
createControl->arguments.Add(arguments.GetByIndex(indexMinSize)[0].expression);
|
|
}
|
|
}
|
|
public:
|
|
GuiRibbonButtonsInstanceLoader()
|
|
:BASE_TYPE(description::TypeInfo<GuiRibbonButtons>::content.typeName, theme::ThemeName::RibbonButtons)
|
|
{
|
|
_MaxSize = GlobalStringKey::Get(L"MaxSize");
|
|
_MinSize = GlobalStringKey::Get(L"MinSize");
|
|
}
|
|
|
|
void GetRequiredPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
if (CanCreate(typeInfo))
|
|
{
|
|
propertyNames.Add(_MaxSize);
|
|
propertyNames.Add(_MinSize);
|
|
}
|
|
}
|
|
|
|
void GetPropertyNames(GuiResourcePrecompileContext& precompileContext, const TypeInfo& typeInfo, collections::List<GlobalStringKey>& propertyNames)override
|
|
{
|
|
GetRequiredPropertyNames(precompileContext, typeInfo, propertyNames);
|
|
}
|
|
|
|
Ptr<GuiInstancePropertyInfo> GetPropertyType(GuiResourcePrecompileContext& precompileContext, const PropertyInfo& propertyInfo)override
|
|
{
|
|
if (propertyInfo.propertyName == _MaxSize || propertyInfo.propertyName == _MinSize)
|
|
{
|
|
auto info = GuiInstancePropertyInfo::Assign(TypeInfoRetriver<RibbonButtonSize>::CreateTypeInfo());
|
|
info->usage = GuiInstancePropertyInfo::ConstructorArgument;
|
|
return info;
|
|
}
|
|
return IGuiInstanceLoader::GetPropertyType(precompileContext, propertyInfo);
|
|
}
|
|
};
|
|
#undef BASE_TYPE
|
|
|
|
/***********************************************************************
|
|
Initialization
|
|
***********************************************************************/
|
|
|
|
void LoadToolstripControls(IGuiInstanceLoaderManager* manager)
|
|
{
|
|
manager->SetLoader(Ptr(new GuiToolstripMenuInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiToolstripMenuBarInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiToolstripToolBarInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiToolstripGroupContainerInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiToolstripGroupInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiToolstripButtonInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiRibbonButtonsInstanceLoader));
|
|
manager->SetLoader(Ptr(new GuiRibbonToolstripMenuInstanceLoader));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/***********************************************************************
|
|
.\INSTANCEQUERY\GUIINSTANCEQUERY.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace collections;
|
|
using namespace instancequery;
|
|
|
|
/***********************************************************************
|
|
ExecuteQueryVisitor
|
|
***********************************************************************/
|
|
|
|
class ExecuteQueryVisitor : public Object, public GuiIqQuery::IVisitor
|
|
{
|
|
public:
|
|
Ptr<GuiInstanceContext> context;
|
|
List<Ptr<GuiConstructorRepr>>& input;
|
|
List<Ptr<GuiConstructorRepr>>& output;
|
|
|
|
ExecuteQueryVisitor(Ptr<GuiInstanceContext> _context, List<Ptr<GuiConstructorRepr>>& _input, List<Ptr<GuiConstructorRepr>>& _output)
|
|
:context(_context), input(_input), output(_output)
|
|
{
|
|
}
|
|
|
|
static bool TestCtor(GuiIqPrimaryQuery* node, GlobalStringKey attribute, Ptr<GuiConstructorRepr> ctor)
|
|
{
|
|
if (node->attributeNameOption == GuiIqNameOption::Specified && node->attributeName.value != attribute.ToString())
|
|
{
|
|
return false;
|
|
}
|
|
if (node->typeNameOption == GuiIqNameOption::Specified && node->typeName.value != ctor->typeName.ToString())
|
|
{
|
|
return false;
|
|
}
|
|
if (node->referenceName.value != L"")
|
|
{
|
|
bool instanceName = ctor->instanceName != GlobalStringKey::Empty && node->referenceName.value == ctor->instanceName.ToString();
|
|
bool styleName = ctor->styleName && node->referenceName.value == ctor->styleName.Value();
|
|
return instanceName || styleName;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Traverse(GuiIqPrimaryQuery* node, Ptr<GuiAttSetterRepr> setter)
|
|
{
|
|
if (setter)
|
|
{
|
|
for (auto [attribute, index] : indexed(setter->setters.Keys()))
|
|
{
|
|
auto setterValue = setter->setters.Values()[index];
|
|
for (auto value : setterValue->values)
|
|
{
|
|
if (auto ctor = value.Cast<GuiConstructorRepr>())
|
|
{
|
|
if (TestCtor(node, attribute, ctor))
|
|
{
|
|
output.Add(ctor);
|
|
}
|
|
}
|
|
if (node->childOption == GuiIqChildOption::Indirect)
|
|
{
|
|
if (auto setter = value.Cast<GuiAttSetterRepr>())
|
|
{
|
|
Traverse(node, setter);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (TestCtor(node, GlobalStringKey::Empty, context->instance))
|
|
{
|
|
output.Add(context->instance);
|
|
}
|
|
if (node->childOption == GuiIqChildOption::Indirect)
|
|
{
|
|
Traverse(node, context->instance);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Visit(GuiIqPrimaryQuery* node)override
|
|
{
|
|
auto inputExists = &input;
|
|
if (inputExists)
|
|
{
|
|
for (auto setter : input)
|
|
{
|
|
Traverse(node, setter);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Traverse(node, 0);
|
|
}
|
|
}
|
|
|
|
void Visit(GuiIqCascadeQuery* node)override
|
|
{
|
|
List<Ptr<GuiConstructorRepr>> temp;
|
|
ExecuteQuery(node->parent, context, input, temp);
|
|
ExecuteQuery(node->child, context, temp, output);
|
|
}
|
|
|
|
void Visit(GuiIqSetQuery* node)override
|
|
{
|
|
List<Ptr<GuiConstructorRepr>> first, second;
|
|
ExecuteQuery(node->first, context, input, first);
|
|
ExecuteQuery(node->second, context, input, second);
|
|
|
|
switch (node->op)
|
|
{
|
|
case GuiIqBinaryOperator::ExclusiveOr:
|
|
CopyFrom(output, From(first).Except(second).Union(From(second).Except(second)));
|
|
break;
|
|
case GuiIqBinaryOperator::Intersect:
|
|
CopyFrom(output, From(first).Intersect(second));
|
|
break;
|
|
case GuiIqBinaryOperator::Union:
|
|
CopyFrom(output, From(first).Union(second));
|
|
break;
|
|
case GuiIqBinaryOperator::Substract:
|
|
CopyFrom(output, From(first).Except(second));
|
|
break;
|
|
default:;
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
ExecuteQuery
|
|
***********************************************************************/
|
|
|
|
void ExecuteQuery(Ptr<GuiIqQuery> query, Ptr<GuiInstanceContext> context, collections::List<Ptr<GuiConstructorRepr>>& input, collections::List<Ptr<GuiConstructorRepr>>& output)
|
|
{
|
|
ExecuteQueryVisitor visitor(context, input, output);
|
|
query->Accept(&visitor);
|
|
}
|
|
|
|
void ExecuteQuery(Ptr<GuiIqQuery> query, Ptr<GuiInstanceContext> context, collections::List<Ptr<GuiConstructorRepr>>& output)
|
|
{
|
|
#if defined(VCZH_GCC) && defined(__clang__)
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wnull-dereference"
|
|
#endif
|
|
ExecuteQuery(query, context, *(List<Ptr<GuiConstructorRepr>>*)0, output);
|
|
#if defined(VCZH_GCC) && defined(__clang__)
|
|
#pragma clang diagnostic pop
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************
|
|
ApplyStyle
|
|
***********************************************************************/
|
|
|
|
void ApplyStyleInternal(Ptr<GuiAttSetterRepr> src, Ptr<GuiAttSetterRepr> dst)
|
|
{
|
|
for (auto [attribute, srcIndex] : indexed(src->setters.Keys()))
|
|
{
|
|
auto srcValue = src->setters.Values()[srcIndex];
|
|
vint dstIndex = dst->setters.Keys().IndexOf(attribute);
|
|
if (dstIndex == -1)
|
|
{
|
|
dst->setters.Add(attribute, srcValue);
|
|
}
|
|
else
|
|
{
|
|
auto dstValue = dst->setters.Values()[dstIndex];
|
|
if (srcValue->binding == dstValue->binding)
|
|
{
|
|
if (srcValue->binding == GlobalStringKey::_Set)
|
|
{
|
|
ApplyStyleInternal(srcValue->values[0].Cast<GuiAttSetterRepr>(), dstValue->values[0].Cast<GuiAttSetterRepr>());
|
|
}
|
|
else
|
|
{
|
|
CopyFrom(dstValue->values, srcValue->values, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto [eventName, srcIndex] : indexed(src->eventHandlers.Keys()))
|
|
{
|
|
if (!dst->eventHandlers.Keys().Contains(eventName))
|
|
{
|
|
auto srcValue = src->eventHandlers.Values()[srcIndex];
|
|
dst->eventHandlers.Add(eventName, srcValue);
|
|
}
|
|
}
|
|
|
|
for (auto [varName, srcIndex] : indexed(src->environmentVariables.Keys()))
|
|
{
|
|
if (!dst->environmentVariables.Keys().Contains(varName))
|
|
{
|
|
auto srcValue = src->environmentVariables.Values()[srcIndex];
|
|
dst->environmentVariables.Add(varName, srcValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ApplyStyle(Ptr<GuiInstanceStyle> style, Ptr<GuiConstructorRepr> ctor)
|
|
{
|
|
ApplyStyleInternal(style->setter->Clone().Cast<GuiAttSetterRepr>(), ctor);
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiIqPrint
|
|
***********************************************************************/
|
|
|
|
class GuiIqPrintVisitor : public Object, public GuiIqQuery::IVisitor
|
|
{
|
|
public:
|
|
stream::StreamWriter& writer;
|
|
|
|
GuiIqPrintVisitor(stream::StreamWriter& _writer)
|
|
:writer(_writer)
|
|
{
|
|
}
|
|
|
|
void Visit(GuiIqPrimaryQuery* node)override
|
|
{
|
|
switch (node->childOption)
|
|
{
|
|
case GuiIqChildOption::Direct:
|
|
writer.WriteString(L"/");
|
|
break;
|
|
case GuiIqChildOption::Indirect:
|
|
writer.WriteString(L"//");
|
|
break;
|
|
default:;
|
|
}
|
|
|
|
if (node->attributeNameOption == GuiIqNameOption::Specified)
|
|
{
|
|
writer.WriteChar(L'@');
|
|
writer.WriteString(node->attributeName.value);
|
|
writer.WriteChar(L':');
|
|
}
|
|
|
|
if (node->typeNameOption == GuiIqNameOption::Specified)
|
|
{
|
|
writer.WriteString(node->typeName.value);
|
|
}
|
|
else
|
|
{
|
|
writer.WriteChar(L'*');
|
|
}
|
|
|
|
if (node->referenceName.value != L"")
|
|
{
|
|
writer.WriteChar(L'.');
|
|
writer.WriteString(node->referenceName.value);
|
|
}
|
|
}
|
|
|
|
void Visit(GuiIqCascadeQuery* node)override
|
|
{
|
|
node->parent->Accept(this);
|
|
node->child->Accept(this);
|
|
}
|
|
|
|
void Visit(GuiIqSetQuery* node)override
|
|
{
|
|
writer.WriteChar(L'(');
|
|
node->first->Accept(this);
|
|
switch (node->op)
|
|
{
|
|
case GuiIqBinaryOperator::ExclusiveOr:
|
|
writer.WriteString(L" ^ ");
|
|
break;
|
|
case GuiIqBinaryOperator::Intersect:
|
|
writer.WriteString(L" * ");
|
|
break;
|
|
case GuiIqBinaryOperator::Union:
|
|
writer.WriteString(L" + ");
|
|
break;
|
|
case GuiIqBinaryOperator::Substract:
|
|
writer.WriteString(L" - ");
|
|
break;
|
|
default:;
|
|
}
|
|
node->second->Accept(this);
|
|
writer.WriteChar(L')');
|
|
}
|
|
};
|
|
|
|
void GuiIqPrint(Ptr<GuiIqQuery> query, stream::StreamWriter& writer)
|
|
{
|
|
GuiIqPrintVisitor visitor(writer);
|
|
query->Accept(&visitor);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\INSTANCEQUERY\GENERATED\GUIINSTANCEQUERYAST.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
This file is generated by: Vczh Parser Generator
|
|
From parser definition:Ast
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl::presentation::instancequery
|
|
{
|
|
/***********************************************************************
|
|
Visitor Pattern Implementation
|
|
***********************************************************************/
|
|
|
|
void GuiIqPrimaryQuery::Accept(GuiIqQuery::IVisitor* visitor)
|
|
{
|
|
visitor->Visit(this);
|
|
}
|
|
|
|
void GuiIqCascadeQuery::Accept(GuiIqQuery::IVisitor* visitor)
|
|
{
|
|
visitor->Visit(this);
|
|
}
|
|
|
|
void GuiIqSetQuery::Accept(GuiIqQuery::IVisitor* visitor)
|
|
{
|
|
visitor->Visit(this);
|
|
}
|
|
}
|
|
namespace vl::reflection::description
|
|
{
|
|
#ifndef VCZH_DEBUG_NO_REFLECTION
|
|
|
|
IMPL_TYPE_INFO_RENAME(vl::presentation::instancequery::GuiIqQuery, presentation::instancequery::GuiIqQuery)
|
|
IMPL_TYPE_INFO_RENAME(vl::presentation::instancequery::GuiIqQuery::IVisitor, presentation::instancequery::GuiIqQuery::IVisitor)
|
|
IMPL_TYPE_INFO_RENAME(vl::presentation::instancequery::GuiIqNameOption, presentation::instancequery::GuiIqNameOption)
|
|
IMPL_TYPE_INFO_RENAME(vl::presentation::instancequery::GuiIqChildOption, presentation::instancequery::GuiIqChildOption)
|
|
IMPL_TYPE_INFO_RENAME(vl::presentation::instancequery::GuiIqPrimaryQuery, presentation::instancequery::GuiIqPrimaryQuery)
|
|
IMPL_TYPE_INFO_RENAME(vl::presentation::instancequery::GuiIqCascadeQuery, presentation::instancequery::GuiIqCascadeQuery)
|
|
IMPL_TYPE_INFO_RENAME(vl::presentation::instancequery::GuiIqBinaryOperator, presentation::instancequery::GuiIqBinaryOperator)
|
|
IMPL_TYPE_INFO_RENAME(vl::presentation::instancequery::GuiIqSetQuery, presentation::instancequery::GuiIqSetQuery)
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
|
|
BEGIN_CLASS_MEMBER(vl::presentation::instancequery::GuiIqQuery)
|
|
CLASS_MEMBER_BASE(vl::glr::ParsingAstBase)
|
|
|
|
END_CLASS_MEMBER(vl::presentation::instancequery::GuiIqQuery)
|
|
|
|
BEGIN_ENUM_ITEM(vl::presentation::instancequery::GuiIqNameOption)
|
|
ENUM_ITEM_NAMESPACE(vl::presentation::instancequery::GuiIqNameOption)
|
|
ENUM_NAMESPACE_ITEM(Specified)
|
|
ENUM_NAMESPACE_ITEM(Any)
|
|
END_ENUM_ITEM(vl::presentation::instancequery::GuiIqNameOption)
|
|
|
|
BEGIN_ENUM_ITEM(vl::presentation::instancequery::GuiIqChildOption)
|
|
ENUM_ITEM_NAMESPACE(vl::presentation::instancequery::GuiIqChildOption)
|
|
ENUM_NAMESPACE_ITEM(Direct)
|
|
ENUM_NAMESPACE_ITEM(Indirect)
|
|
END_ENUM_ITEM(vl::presentation::instancequery::GuiIqChildOption)
|
|
|
|
BEGIN_CLASS_MEMBER(vl::presentation::instancequery::GuiIqPrimaryQuery)
|
|
CLASS_MEMBER_BASE(vl::presentation::instancequery::GuiIqQuery)
|
|
|
|
CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::presentation::instancequery::GuiIqPrimaryQuery>(), NO_PARAMETER)
|
|
|
|
CLASS_MEMBER_FIELD(childOption)
|
|
CLASS_MEMBER_FIELD(attributeNameOption)
|
|
CLASS_MEMBER_FIELD(attributeName)
|
|
CLASS_MEMBER_FIELD(typeNameOption)
|
|
CLASS_MEMBER_FIELD(typeName)
|
|
CLASS_MEMBER_FIELD(referenceName)
|
|
END_CLASS_MEMBER(vl::presentation::instancequery::GuiIqPrimaryQuery)
|
|
|
|
BEGIN_CLASS_MEMBER(vl::presentation::instancequery::GuiIqCascadeQuery)
|
|
CLASS_MEMBER_BASE(vl::presentation::instancequery::GuiIqQuery)
|
|
|
|
CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::presentation::instancequery::GuiIqCascadeQuery>(), NO_PARAMETER)
|
|
|
|
CLASS_MEMBER_FIELD(parent)
|
|
CLASS_MEMBER_FIELD(child)
|
|
END_CLASS_MEMBER(vl::presentation::instancequery::GuiIqCascadeQuery)
|
|
|
|
BEGIN_ENUM_ITEM(vl::presentation::instancequery::GuiIqBinaryOperator)
|
|
ENUM_ITEM_NAMESPACE(vl::presentation::instancequery::GuiIqBinaryOperator)
|
|
ENUM_NAMESPACE_ITEM(ExclusiveOr)
|
|
ENUM_NAMESPACE_ITEM(Intersect)
|
|
ENUM_NAMESPACE_ITEM(Union)
|
|
ENUM_NAMESPACE_ITEM(Substract)
|
|
END_ENUM_ITEM(vl::presentation::instancequery::GuiIqBinaryOperator)
|
|
|
|
BEGIN_CLASS_MEMBER(vl::presentation::instancequery::GuiIqSetQuery)
|
|
CLASS_MEMBER_BASE(vl::presentation::instancequery::GuiIqQuery)
|
|
|
|
CLASS_MEMBER_CONSTRUCTOR(vl::Ptr<vl::presentation::instancequery::GuiIqSetQuery>(), NO_PARAMETER)
|
|
|
|
CLASS_MEMBER_FIELD(first)
|
|
CLASS_MEMBER_FIELD(second)
|
|
CLASS_MEMBER_FIELD(op)
|
|
END_CLASS_MEMBER(vl::presentation::instancequery::GuiIqSetQuery)
|
|
|
|
BEGIN_INTERFACE_MEMBER(vl::presentation::instancequery::GuiIqQuery::IVisitor)
|
|
CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::presentation::instancequery::GuiIqQuery::IVisitor::*)(vl::presentation::instancequery::GuiIqPrimaryQuery* node))
|
|
CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::presentation::instancequery::GuiIqQuery::IVisitor::*)(vl::presentation::instancequery::GuiIqCascadeQuery* node))
|
|
CLASS_MEMBER_METHOD_OVERLOAD(Visit, {L"node"}, void(vl::presentation::instancequery::GuiIqQuery::IVisitor::*)(vl::presentation::instancequery::GuiIqSetQuery* node))
|
|
END_INTERFACE_MEMBER(vl::presentation::instancequery::GuiIqQuery)
|
|
|
|
#endif
|
|
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
class GuiInstanceQueryAstTypeLoader : public vl::Object, public ITypeLoader
|
|
{
|
|
public:
|
|
void Load(ITypeManager* manager)
|
|
{
|
|
ADD_TYPE_INFO(vl::presentation::instancequery::GuiIqQuery)
|
|
ADD_TYPE_INFO(vl::presentation::instancequery::GuiIqQuery::IVisitor)
|
|
ADD_TYPE_INFO(vl::presentation::instancequery::GuiIqNameOption)
|
|
ADD_TYPE_INFO(vl::presentation::instancequery::GuiIqChildOption)
|
|
ADD_TYPE_INFO(vl::presentation::instancequery::GuiIqPrimaryQuery)
|
|
ADD_TYPE_INFO(vl::presentation::instancequery::GuiIqCascadeQuery)
|
|
ADD_TYPE_INFO(vl::presentation::instancequery::GuiIqBinaryOperator)
|
|
ADD_TYPE_INFO(vl::presentation::instancequery::GuiIqSetQuery)
|
|
}
|
|
|
|
void Unload(ITypeManager* manager)
|
|
{
|
|
}
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
bool GuiInstanceQueryAstLoadTypes()
|
|
{
|
|
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
|
|
if (auto manager = GetGlobalTypeManager())
|
|
{
|
|
auto loader = Ptr(new GuiInstanceQueryAstTypeLoader);
|
|
return manager->AddTypeLoader(loader);
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\INSTANCEQUERY\GENERATED\GUIINSTANCEQUERYPARSER.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
This file is generated by: Vczh Parser Generator
|
|
From parser definition:GuiInstanceQuery
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl::presentation::instancequery
|
|
{
|
|
void GuiInstanceQueryParserData(vl::stream::IStream& outputStream)
|
|
{
|
|
static const vl::vint dataLength = 3046; // 28794 bytes before compressing
|
|
static const vl::vint dataBlock = 256;
|
|
static const vl::vint dataRemain = 230;
|
|
static const vl::vint dataSolidRows = 11;
|
|
static const vl::vint dataRows = 12;
|
|
static const char* compressed[] = {
|
|
"\x7A\x70\x00\x00\xDE\x0B\x00\x00\x0D\x00\x01\x82\x80\x07\x03\x82\x81\x82\x06\x89\x82\x88\x0A\x87\x06\x84\x0C\x0A\x9D\x0A\x86\x1A\x87\x16\x84\x77\x02\x09\xBF\x7B\x8C\x8B\x8E\x84\x00\x1D\x9D\x9F\x81\x9C\x8B\x90\x93\x7F\x1F\x9F\x81\x0A\x8B\x91\x85\x96\x83\x27\xA8\x8A\x91\x96\x94\x91\x9B\x90\x37\xA2\xB3\x87\x99\x9D\x93\x9C\x9B\x3F\xB8\x81\xBA\x9A\x8C\x9F\xA0\x9F\x45\xC0\x89\xA2\xAB\xA4\xA0\x98\xA3\x4D\xC8\x8F\xAA\xA3\xAC\xA5\xAA\xA7\x03\xB4\x87\xBE\x8B\xAA\x99\xA8\xAE\x09\x99\xAE\x9D\xAD\x98\xB3\xAA\xA9\x59\xD0\xA7\xA6\xB9\xB4\xA9\xB6\xAB\x6F\xD8\x82\x9A\xAF\xAE\xAF\xB4\xBB\x71\xE8\x82\x83\x0C\x94\xB2\xBF\xBA\x65\xF8\xB3\xAA\xB3\x84\x01\xBE\xC0\x7F\xF7\x81\xCB\xC9\xC1\xBC\xB7\xC1\x6E\x90\xF0\xB2\xC2\xB9\x81\x03\xC3\x8A\x8D\xD4\xDA\xB1\x84\xB9\xCC\xC4\xA0\x9F\xE2\xCE\xC2\xC5\xCC\xC3\xCD\x8F\xA6\xD1\xCA\xD3\xC9\x82\x02\xCC\xA4\x8C\xE1\xD1\xDA\xCC\xD5\xCA\x90\xA7\xB6\xDC\xD8\xDB\xD4\xDD\xD6\xDF\xB7\x9E\xC3\x88\x86\x87\x94\xDB\xD9\xA8\xA5\xC0\xFB\xD2\xE3\x84\xD9\xE4\xB2\xA3\xD0\xF5\xDB\xE1\xD5\xEA\xE5\xCD\xBA\xD6\xF9",
|
|
"\xE0\x01\x07\xE6\xED\xD8\xB9\xD7\xF1\xE7\xE2\xE8\xF0\xF2\xD3\xC8\xE7\xF4\xEC\xED\xF6\xF0\xF7\xBD\xDC\xCA\x1F\xE0\x03\x04\xFA\xF8\xBF\xF8\xC1\xE2\xFC\x07\xFB\xF7\xFF\xF1\x40\x89\x7E\x80\xFB\x41\x86\x83\x80\x07\x85\x88\x83\x82\x0A\x8D\x8C\x72\x78\x00\x63\x5A\x7B\x78\xEC\x44\x8F\x81\x82\x17\x8C\x89\x86\x83\xDB\x56\x8D\x84\x86\x1F\x9A\x81\x8B\x6D\x0E\x3E\x70\x89\x78\x27\xA8\x7B\x7B\x84\x0E\x52\x86\x78\x85\x13\xBA\x7B\x87\x8C\x23\xB4\x88\x8A\x88\x37\x9C\x89\x8F\x6E\x10\x26\x88\x8F\x47\x11\x3E\x8A\x8E\x8A\x30\xAF\x82\x8D\x8D\x48\xBB\x89\x90\x91\x47\x8A\x9E\x90\x93\xE2\x52\x04\x7F\x04\x42\xB6\x80\x95\x8A\x15\x98\x91\x8E\x87\xCA\x54\x04\x7D\x05\x55\x8B\x9A\x42\x05\x61\x8F\x99\x97\x8F\x67\x83\x99\x9A\x95\x6B\xA2\x9B\x96\x96\x46\x9C\x97\x94\x9A\x09\x57\x05\x9B\x9C\x6A\xAF\x94\x9D\x9C\x70\xA5\x7E\x9D\x7A\x7C\xBB\x9F\x9F\x8A\x81\xB9\x96\x40\x44\x2E\x83\xA5\x92\xA2\x4D\xB8\x9C\x9B\x84\x19\x34\x7A\x07\x9D\xD4\x5B\x04\xA6\x9E\x86\x8C\xA2\x9C\x75\x1C\x17\xA5\xA3\xA3\x9F\xAE\x91\xAA\x99\x98\xA0\xAA\xA5\x9F\x80\x8A\xA2\x45\xA2",
|
|
"\x02\x5E\x0E\xA7\xA9\x82\xA9\xA2\x43\x07\xAF\xB2\xA4\xA3\x40\x20\x35\xA7\xAE\xAD\x8B\xBC\xAD\xA1\x9B\xA4\xA3\xAE\xA2\xA8\xB0\x99\xA2\x41\x08\xF4\x62\x0A\xAD\xAF\xBB\x8D\xBC\xB0\x00\x23\x0B\xBF\xAD\xA9\xD6\x64\x04\x7D\x09\xD2\xA2\x74\x44\xAB\xCE\x93\xB2\xB0\xB0\xC3\x81\xB5\xB2\xA9\xBE\x9B\xA4\xB6\xB8\xE5\xA8\xAD\xB6\xB9\x06\x67\x04\x7C\x0A\xD9\xBD\x69\x09\xBC\xB1\xAB\xBA\xBB\xB3\xDC\x6A\x04\x7F\x0A\xF4\x86\xB6\xBD\xBD\xF8\xAC\xB3\xB8\xB1\xBC\xAC\x04\x7D\x0B\xFD\xA4\xBF\xBE\xBF\x01\xF7\xBE\xB7\xC0\xE8\x8E\xBE\x08\x7D\x16\x5C\xBD\xC3\x6F\x30\x09\xC4\xC3\xC2\x0A\xD7\xCC\xC3\xC3\xE9\x80\xC0\xC8\xC7\x1B\xDE\xCD\xC7\xC8\xCF\xB1\x04\x7E\x0C\x1A\xCA\x73\x0D\xCB\xE1\xB1\xC0\xBA\x42\x34\x34\x75\x0E\x42\x62\x5F\xB7\xBA\xCC\x3B\xF3\xCD\xCF\xCF\x2F\xB7\x04\x7C\x0E\x30\xCA\x49\x0D\xD1\x40\xD0\xCC\xCE\x41\x3A\x34\x7B\x0C\xCE\x3E\xFA\xC2\xD6\xD2\x51\xD4\xD9\xD1\xC8\x1F\xE2\x7D\x0C\xD2\x53\xD8\xD7\xCA\xC0\x5E\xE5\xC8\xCB\xD8\xE2\x7E\x0C\xD6\xD5\x5D\xC1\x4F\x0C\x7D\x40\x10\xD7\xD4\xC9\x11\xE6\xC2\xD8\xD8\x70\xCB\xDA\xA2\x10\xF4",
|
|
"\x43\x17\xDA\x40\x44\x3B\xD5\xDD\xD5\x61\xF1\xD4\xDA\xC3\x74\xF2\xD2\xE1\xE1\x83\xE2\xC2\x79\x11\xF4\x46\x1E\xDC\x00\x47\x0F\xE9\xE1\xD6\xF7\x88\x14\x7D\x12\x6E\xE9\xD6\xE2\xDD\x81\xDC\xEF\xDF\xDB\xCF\x8B\x14\x7C\x13\x8F\xCD\x12\xE4\xE2\xA8\xF7\xBE\x10\x7D\x4F\x19\xE8\xDB\xEB\x9D\xC0\xEF\xE6\xE6\x93\xDF\xD4\xE3\xED\x00\xD1\x17\xE8\xEE\x94\xCA\xEC\xEE\xED\xBE\xFF\x62\x17\xEE\x00\xD3\x14\x7C\x15\xAE\xF1\xE0\xE9\xED\x73\xFF\xED\xF1\xF0\xB7\x56\x14\x7F\x15\x8F\xD8\x14\xF1\xEF\xD8\xC0\xF9\xF7\xF3\xDB\xC7\xEE\xF2\xF7\xD0\xFB\x69\x17\xF5\xDA\xE5\xFC\xF6\xF9\xE0\xCC\xCE\x02\x71\x01\x79\xC3\x40\xFB\x70\xF1\x4E\x75\x42\xAF\x75\x5E\xFA\x40\xF0\xD7\x79\xFD\xFE\xF2\xCA\x44\x70\x69\x97\x35\x2D\x93\x7D\x79\x21\x00\xB7\x2B\x7F\x5D\x33\x7E\x41\x7F\x79\x38\x03\xA4\x31\x26\xF9\x61\x32\x02\xC3\x3D\x2A\x07\x89\x3B\x80\x27\x33\x82\x40\x16\x80\x3D\x08\x89\x86\x7F\x15\x9D\x29\x4C\x7C\x22\x81\x93\x37\x79\x20\xFC\x7C\x48\x01\x86\x25\x7F\xBB\x24\x87\x2E\x31\x27\x84\x00\x29\x84\x25\x17\x8F\x87\x24\x86\x25\x84\x49\x08\x85\x2E\x0D\x81\x26",
|
|
"\x86\x0D\x82\x86\x0A\x99\x89\x79\x0E\xA9\x25\x87\x0A\x20\x88\x78\x1C\x87\x3B\x18\xAD\x63\x85\x03\x2D\x84\x69\x32\x84\x87\x90\x0A\x8D\x89\x27\x37\x89\x4C\x23\x82\x88\x92\x0C\x8B\x8B\x59\x9D\x8A\x15\xE2\x8D\x22\x2D\xA0\x8B\x8C\x3A\x88\x8C\x0C\xE1\x89\x8D\x32\xA4\x8C\x23\x66\x87\x8C\x1C\xEF\x8B\x23\x38\xB2\x8F\x1F\x76\x92\x8D\x1E\xE7\x8B\x8E\x30\xBD\x8B\x8B\x7F\x90\x83\x11\xF7\x2E\x86\x00\x39\x87\x2E\x5F\x97\x8D\x1D\xF4\x8F\x1E\x2A\x80\x58\x8A\x02\x32\x89\x72\x01\x96\x85\x32\x54\x93\x87\x65\x45\x93\x21\x80\x8C\x91\x4B\xA1\x26\x91\xE7\x50\x92\x6B\x5D\x2E\x93\x8E\x20\x96\x85\x9D\x89\x95\x1B\xF3\x8B\x95\x45\xAD\x90\x8F\xAA\x8B\x8D\x0D\xB1\x97\x87\x59\xAF\x91\x91\x8A\x98\x97\x1D\x8C\x80\x3C\x27\x83\x91\x39\x0C\x2F\x95\x21\xD5\x8D\x22\x5D\xB2\x8E\x98\x67\x9C\x94\x16\xA4\x22\x87\xC0\x01\x9A\x96\x21\x23\x98\x29\xB4\x97\x82\x36\x90\x9E\x8D\xAF\x85\x94\x2B\xD7\x9B\x9B\x5A\xAA\x8E\x9B\xD8\x9C\x9A\x2B\xE2\x90\x97\x6C\x94\x9D\x97\xD6\x80\x9D\x37\xD5\x98\x92\x8B\x62\x95\x3B\x21\x8F\x94\x0F\x84\x9A\x21\x42\xB1\x20\x99\x60\x8A",
|
|
"\x9A\x22\x9B\x22\x87\x3F\x8F\x9A\x9D\x1B\x25\x93\x3F\xC9\x33\x9E\xD2\x05\x96\x9E\x27\x38\x9F\x16\xFA\x9B\x9F\x7E\x9D\x2B\xA0\xE8\x84\x26\x40\xD3\x96\x9D\x8A\xA4\x9A\x9B\xE3\x80\xA1\x39\xE4\x9E\x82\x24\x89\x20\xA1\x5E\x8C\x91\x47\xF4\x9F\xA3\x78\xA4\x9C\xA1\x8A\x8E\xA1\x5D\x10\xAB\x99\x68\x8A\x24\xA5\x82\x9F\x94\x78\x07\xA6\xA4\x8D\xA8\xA7\x8E\x2A\xB7\x2C\x4C\xFB\x93\xA3\xBA\x0A\xA7\x9E\x8C\x97\xA6\x1C\xB9\xA4\x35\x9D\x8A\x95\xA7\x88\x81\xA8\x23\xC4\xA0\x98\x46\x88\xAC\x34\x18\xBB\xA2\x46\xD1\xA4\xAB\x73\xAD\xA1\x9C\x53\xB6\xAB\x3E\xD2\xAC\x9D\x6F\x9D\xA8\xAB\x5F\xAB\x9D\x44\xDE\xA3\xAC\xB0\xA5\xAA\xAC\x57\xA8\xAF\x56\xD5\xA6\xA3\xAC\xB2\x9D\x88\xD7\x34\xA6\x4F\xA2\xA0\xAF\x77\xA0\xA1\x24\x3F\xA7\x26\x50\xE7\x8C\xA8\xF0\x06\xAF\x8E\x4F\xA4\xA1\x5D\xC4\x85\xA5\xB9\xAF\x93\xAF\x60\x9D\xAF\x75\x7F\xA2\x8F\xC0\xA0\x3C\xAD\x17\xBA\xAB\x3E\x90\xBE\xAD\xC8\xAD\xA9\xAC\x1B\x39\x7F\x1F\xF2\xA9\xA9\xB7\x89\x23\xB3\xF5\x95\xA4\x66\xFF\x18\xB1\x2D\x8A\xB1\x26\x8C\xA7\x8E\x63\xFA\x79\x89\x0F\x85\xB5\xB3\x27\xAB\xA9\x6B\xAB",
|
|
"\xAE\xA9\x97\xA2\xB7\xAC\x1B\x39\xAC\x49\x25\xBE\x96\x83\x3E\x9D\xB6\x09\x29\xB5\x6E\xCA\xAF\x95\xD3\xA7\x22\xB8\x5B\x8B\xB4\x17\x97\xB8\xB6\xAE\x8D\xBC\xB2\xA3\xB0\xBB\x73\x92\xBA\x90\xE9\xA9\xA9\xA3\xD1\xB4\xBB\x1D\xD1\xAB\x93\xD1\xBA\xB1\x24\xDD\xAD\xB9\x78\xD7\xBF\x1F\xF1\x9B\xAE\xBC\xFB\x88\xBE\x22\xEA\xB7\x8E\xF6\x8D\xB2\xA6\x33\xAA\x23\x7C\x1E\xA6\x21\xF9\xA4\xA5\xBE\xAE\xB8\xBD\x5D\x5C\x00\xBF\x94\x05\xA2\x20\x8A\xA3\xBC\x13\x92\x9D\x7D\xD9\x86\x22\xC0\x0A\x24\xC0\x00\x01\xCA\x21\x01\xE0\x80\xBE\xCA\x9F\x22\x32\xAC\xAF\x22\x0A\xF6\xB4\x7E\x09\xD9\xC3\x6B\x83\x2C\xB3\x81\x0E\xC5\x80\x1A\xC6\x23\x87\xFA\xBC\x84\xF9\xA1\xC3\x20\xF6\xB1\x8A\x42\x76\x38\xC3\x84\x2C\xC5\xC4\x2E\xC7\xC6\x40\x08\xCD\xC5\x03\xCD\xC2\xC6\x01\x34\xC4\x8C\x86\x2D\x3E\x10\xF5\xC3\x20\x3D\xC2\xC4\x8E\x80\x01\xC8\x0F\xC3\xC9\x42\x42\xDF\xC6\x40\x48\xC6\xC8\x25\xC1\x24\xC9\x1B\x83\xCB\x15\xBA\xCA\xC5\xCF\x8A\x24\xCA\x91\x86\xC1\x61\x37\xCE\xC8\x00\x25\x40\xBE\x29\xC3\x93\x1F\xFD\xB0\x00\x28\xC7\x8F\x8A\x02\x10\x7D\xFE\x0A\xC2\x4A\xF8",
|
|
"\x97\x8B\x00\x6A\xDC\xCA\x41\x2A\x6E\xCC\xEA\x23\xBB\x62\x75\xC9\x20\x01\x71\xC6\xCB\x84\x18\x59\xCF\x22\xDC\xCE\x41\x32\x8D\x52\x40\xD1\x8A\xD0\xEF\x6A\x22\x97\x06\xD7\x20\x44\xF8\x7B\x4C\xFD\xB7\x88\x02\x0E\xD5\xC1\x84\x16\x54\xCC\x1F\xB4\xD0\x00\x57\x89\x56\x4C\xF5\xBA\xD3\x57\x8A\x5A\xA7\x83\x2B\x00\x4D\xE3\xBB\x5E\xA3\xC2\x20\x03\x26\xDA\x20\x7E\x69\xD7\xC9\x9A\xDA\x09\x7F\x8A\xAF\xD5\x47\xD6\x62\x86\xDC\x3F\x20\xAE\xE2\x3F\x23\x2B\x84\x9D\x63\xA7\x8A\x53\x47\x63\xB3\xCC\xEA\x06\xBD\x37\x9E\x6F\x5B\x94\xD4\x34\x48\x65\xBB\xD5\x37\xE3\xBF\xD6\x75\x1F\x25\x91\x62\xD3\x44\x89\xD2\xCA\x3B\x47\x45\xCB\x2E\xD9\x40\x03\xC4\xC2\xDE\xD8\x77\x0A\xC5\xB4\x32\xDC\x3D\x45\x83\xD4\x3A\x32\xD9\xD4\xCD\x20\x7D\xCA\x73\x2C\xB4\xD5\x7F\x8B\xD9\xDD\x84\x24\x49\x2C\xFD\xB9\x7C\x4B\xCF\xDF\x37\x8F\x08\x55\xDE\x2F\x5F\xBD\x40\x2C\xAF\xC5\x70\xC9\x23\x52\xEE\x85\x71\x98\x81\x27\xAF\xDB\x1F\x27\xD2\x36\xC0\x75\xC1\xAA\xDC\xD8\xEA\x34\x50\xDF\x13\x53\xE1\x40\x5F\xCF\x45\x64\xDC\x3C\xDB\x1B\xF5\xE3\xF2\x10\x41\xB5\x09\x5F\x20\x59",
|
|
"\xEF\xD0\x75\xC8\xBE\xCD\xE2\x85\x16\x5E\x62\x7F\xC0\xE3\x40\x41\xD2\x20\x8E\xF3\xE2\xE4\xED\x4B\x5A\xAF\x8D\x2A\x20\x3B\x66\xE2\x21\xF0\x49\xE3\xBD\x68\xD3\x20\x30\x7F\xE1\x21\xA8\xC5\x3A\xB7\xC4\xE2\x20\x2A\x47\xEE\x20\xFA\x42\xE8\xC0\x6E\xD6\x21\x1E\x4F\xEB\x20\xAE\xCA\xE8\xE8\x6D\xC6\x20\xAA\xC6\xE4\x76\xE2\x2E\xEA\x41\x3E\xED\xE5\x84\x06\x64\xE5\x8A\x58\xC9\x40\x62\xE5\xE8\x9C\xC3\x24\xCE\x49\xCF\x45\x21\xCC\x8C\xED\xA6\xEE\xEA\x20\x36\x12\xCE\xA2\x36\xE1\xCB\x84\x34\xDB\x20\x56\xE5\xEE\x41\x4F\x69\xE4\xE5\x46\x26\xE8\x71\xFF\xEB\x40\x66\x68\xE2\x83\x2D\x6D\xF1\x03\x35\xED\xA5\x87\xF3\xB0\x64\xCA\x20\x6F\x90\xFC\x54\xE2\xB7\xE9\x21\xCD\xC2\x22\xE3\xCF\x5F\x21\xDF\x52\xE7\x36\xB2\xC9\xD6\xDE\x0A\x21\xF2\xE2\x82\x2C\x71\xC2\xF3\x73\x20\xA6\xFD\xEE\xE0\x83\x26\x73\xCC\xC1\x22\x09\x70\xBF\xDC\xE7\xE3\xE5\xF3\x7E\xCA\x24\x74\xB6\xEF\x58\xC2\xB2\xE2\x21\xD8\xC1\x20\xF4\xB9\xCA\x23\xEA\x24\xFB\x37\x42\xDA\xEF\x50\x3D\xF7\xED\x40\x2D\x71\xF8\xEE\x2B\x57\xF9\x03\x3A\xF6\x40\x1E\xFE\x59\x8F\x3A\x75\xFA\xE2\x2E\x56",
|
|
"\xC5\x5A\xFB\xEC\xE9\xC0\x06\x78\xE0\xFD\x37\xC5\xD8\xF2\x21\xE1\xF0\xF6\xFC\x55\x0B\x59\xA7\xEC\xF1\x20\xF7\xDB\xFE\xFC\xD2\x6C\xFA\x75\x28\xE4\xFE\x00\x36\xFD\xFC\x57\x72\x10\xD4\x3A\x7F\xCA\x12\x6A\xFD\x70\x71\x03\x11\x29\x01\x81\x10\xD6\x34\x80\x44\x28\x80\xED\x76\x7E\xE3\x3A\x67\x0A\x1D\x05\xCB\x2E\x7C\x09\x86\x7E\x5E\x0F\x38\x18\x81\x81\x0B\x80\x00\x5F\x07\x65\x0A\x13\x06\xCB\x27\x7D\xEF\x7F\x81\x64\x0A\x65\xBC\x21\x2D\xC1\x76\x82\xF7\x7F\x81\x67\x0A\x82\xCE\x21\x73\xBB\x73\x10\x2E\x80\x80\xB3\x72\x10\x6A\x02\x83\xCF\x2E\x2E\xC1\x7B\x7E\x27\x89\x83\x01\x1D\x06\xBD\x77\x1B\x49\x75\x83\xB3\x2A\x10\xDC\x71\x7A\x0A\x1F\x06\x45\x8B\x1B\x59\x78\x84\x01\x10\x84\x76\x7F\x81\x71\x0F\x84\xD6\x18\x30\xC1\x73\x7F\x03\x12\x7E\x42\x80\x00\x73\x0C\x83\x28\x3C\x85\x02\x1C\x82\x5F\x86\x07\x43\x6C\x07\xF2\x7E\x72\xE6\x7D\x07\x43\x63\x08\xCB\x2C\x7F\x41\x8B\x7A\x01\x14\x08\x58\x8A\x1C\x15\x34\x7C\x01\x12\x87\x2F\x8F\x85\x86\x07\x87\x1F\x10\x77\x52\x80\x00\x7C\x88\x83\x74\x80\x00\x88\x00\x88\x0A\x1F\x32\xC1\x76\x80\x5D\x86",
|
|
"\x7E\x8A\x02\x86\x85\x3E\x88\x65\x86\x7E\x8D\x03\x64\x93\x0B\x2C\x94\x81\x10\x2F\x7F\x85\x94\x03\x64\x9A\x0B\x2C\x66\x83\x10\x54\x8D\x7D\xE2\x62\x1E\x9D\x83\x10\x85\x8C\x84\x23\x7D\x1B\x34\x8D\x2A\xE6\x7B\x09\x8F\x3F\x8A\x01\x13\x8A\xBC\x2F\x11\x9C\x02\x82\x09\x10\x0A\xCB\x24\x8B\x00\x09\x8A\xB7\x8A\x10\xA1\x0A\x8B\x06\x15\x0A\xCB\x2B\x2D\xBC\x7F\x81\xA6\x04\x8C\x8A\x27\x33\xAE\x70\x00\xC8\x8D\x76\x1F\x8A\x0A\xCC\x8C\x2B\x44\x3F\x8C\xD1\x85\x85\x5F\x8E\x0A\xD5\x8E\x2C\x84\x7E\x5B\x40\x71\x7D\x1F\x82\x0B\x92\x8D\x1B\x8C\x70\x8E\x09\x11\x74\x94\x7F\x81\xB5\x05\x8E\xBF\x11\x04\x3C\x8A\x8E\x91\x76\x7E\xB8\x0E\x8E\xB7\x13\x7A\xE8\x86\x10\x47\x82\x10\x3E\x8F\x85\xBB\x06\x8F\x1D\x3B\x8F\x01\x17\x76\x5F\x8E\x0B\x43\x64\x0C\xCB\x22\x90\x00\x0A\x85\x5F\x85\x0C\x43\x6B\x0C\xCB\x21\x75\xC9\x8F\x85\xCC\x00\x90\xD6\x11\x39\xCF\x82\x91\xD2\x8F\x85\xCF\x06\x91\xCA\x18\x7B\x19\x9A\x10\x92\x7C\x8A\x06\x12\x0D\x1E\x9F\x11\xA6\x3F\x8C\x51\x8C\x8F\xE6\x75\x0D\x27\x94\x1D\x2B\x93\x90\xE6\x78\x0D\x43\x6E\x0D\xCB\x21\x93\x0B\x96\x7E",
|
|
"\xDF\x03\x64\xE5\x0B\x2C\x04\x93\x10\xF2\x81\x8C\xAD\x8F\x1B\x0C\x93\x10\x1A\x92\x94\x60\x7D\x1B\x78\x69\x73\x1F\x86\x0E\x8F\x3B\x94\x03\x1F\x93\x48\x93\x10\xE7\x0D\x8D\x00\x0B\x0E\xCB\x20\x95\x02\x15\x94\x53\x92\x10\xEC\x06\x95\xF0\x0B\x2C\x79\x83\x87\x5D\x91\x10\xF1\x0A\x77\xBC\x20\x05\x56\x93\x96\x7D\x87\x88\xF6\x08\x96\xCE\x28\x3C\x14\x89\x10\x6C\x96\x88\x65\x90\x00\xFB\x00\x97\xCF\x2D\x80\x11\x73\x67\x0A\x19\x31\x1F\x83\x43\xE9\x70\x30\x2C\x30\x5F\xB9\x6B\x45\xB5\x69\x98\xF0\x53\x52\xFD\x7E\x5F\x2A\x14\x16\xD9\x6F\x0F\x8C\x97\x7A\x8D\x92\x70\x28\x44\x1F\x82\x96\x31\x0B\x64\x16\xFC\x6F\x49\x70\x5B\x99\xC1\x70\x9A\x7A\x83\x79\x32\x5D\x4C\xBA\x68\x99\x34\x7D\x6D\x80\x11\x48\x3B\x7C\x83\x11\x47\x45\x29\x1E\x5E\x25\x12\x9B\x1C\x13\x5E\xCD\x46\x9B\xC3\x68\x99\xD1\x69\x9B\xA1\x9B\x9B\x56\x99\x12\xB4\x6F\x53\xD8\x6F\x11\xC3\x9A\x97\xCD\x4C\x44\xC7\x98\x99\xC8\x94\x9C\x64\x6A\x60\x34\x1E\x9C\x31\x1A\x60\x98\x60",
|
|
};
|
|
vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream);
|
|
}
|
|
|
|
const wchar_t* ParserRuleName(vl::vint index)
|
|
{
|
|
static const wchar_t* results[] = {
|
|
L"QPrimaryFragment",
|
|
L"QPrimaryAttributed",
|
|
L"QPrimary",
|
|
L"Query0",
|
|
L"Query1",
|
|
L"Query2",
|
|
L"QueryRoot",
|
|
};
|
|
return results[index];
|
|
}
|
|
|
|
const wchar_t* ParserStateLabel(vl::vint index)
|
|
{
|
|
static const wchar_t* results[] = {
|
|
L"[0][QPrimaryFragment] BEGIN ",
|
|
L"[1][QPrimaryFragment] END [ENDING]",
|
|
L"[2][QPrimaryFragment]< \"*\" @ [ \".\" NAME ] >",
|
|
L"[3][QPrimaryFragment]< \"*\" [ \".\" @ NAME ] >",
|
|
L"[4][QPrimaryFragment]< \"*\" [ \".\" NAME @ ] >",
|
|
L"[5][QPrimaryFragment]< NAME @ [ \".\" NAME ] >",
|
|
L"[6][QPrimaryFragment]< NAME [ \".\" @ NAME ] >",
|
|
L"[7][QPrimaryFragment]< NAME [ \".\" NAME @ ] >",
|
|
L"[8][QPrimaryAttributed] BEGIN ",
|
|
L"[9][QPrimaryAttributed] END [ENDING]",
|
|
L"[10][QPrimaryAttributed]<< !QPrimaryFragment @ >>",
|
|
L"[11][QPrimaryAttributed]<< \"@\" @ [ NAME ] \":\" !QPrimaryFragment >>",
|
|
L"[12][QPrimaryAttributed]<< \"@\" [ NAME @ ] \":\" !QPrimaryFragment >>",
|
|
L"[13][QPrimaryAttributed]<< \"@\" [ NAME ] \":\" !QPrimaryFragment @ >>",
|
|
L"[14][QPrimaryAttributed]<< \"@\" [ NAME ] \":\" @ !QPrimaryFragment >>",
|
|
L"[15][QPrimary] BEGIN ",
|
|
L"[16][QPrimary] END [ENDING]",
|
|
L"[17][QPrimary]<< \"(\" !QueryRoot \")\" @ >>",
|
|
L"[18][QPrimary]<< \"(\" !QueryRoot @ \")\" >>",
|
|
L"[19][QPrimary]<< \"(\" @ !QueryRoot \")\" >>",
|
|
L"[20][QPrimary]<< \"/\" !QPrimaryAttributed @ >>",
|
|
L"[21][QPrimary]<< \"/\" @ !QPrimaryAttributed >>",
|
|
L"[22][QPrimary]<< \"//\" !QPrimaryAttributed @ >>",
|
|
L"[23][QPrimary]<< \"//\" @ !QPrimaryAttributed >>",
|
|
L"[24][Query0] BEGIN ",
|
|
L"[25][Query0] END [ENDING]",
|
|
L"[26][Query0]< Query0 @ QPrimary >",
|
|
L"[27][Query0]< Query0 QPrimary @ >",
|
|
L"[28][Query0]<< !QPrimary @ >>",
|
|
L"[29][Query1] BEGIN ",
|
|
L"[30][Query1] END [ENDING]",
|
|
L"[31][Query1]< Query1 \"*\" @ Query0 >",
|
|
L"[32][Query1]< Query1 \"*\" Query0 @ >",
|
|
L"[33][Query1]< Query1 \"^\" @ Query0 >",
|
|
L"[34][Query1]< Query1 \"^\" Query0 @ >",
|
|
L"[35][Query1]< Query1 @ \"*\" Query0 >",
|
|
L"[36][Query1]< Query1 @ \"^\" Query0 >",
|
|
L"[37][Query1]<< !Query0 @ >>",
|
|
L"[38][Query2] BEGIN ",
|
|
L"[39][Query2] END [ENDING]",
|
|
L"[40][Query2]< Query2 \"+\" @ Query1 >",
|
|
L"[41][Query2]< Query2 \"+\" Query1 @ >",
|
|
L"[42][Query2]< Query2 \"-\" @ Query1 >",
|
|
L"[43][Query2]< Query2 \"-\" Query1 @ >",
|
|
L"[44][Query2]< Query2 @ \"+\" Query1 >",
|
|
L"[45][Query2]< Query2 @ \"-\" Query1 >",
|
|
L"[46][Query2]<< !Query1 @ >>",
|
|
L"[47][QueryRoot] BEGIN ",
|
|
L"[48][QueryRoot] END [ENDING]",
|
|
L"[49][QueryRoot]<< !Query2 @ >>",
|
|
};
|
|
return results[index];
|
|
}
|
|
|
|
Parser::Parser()
|
|
: vl::glr::ParserBase<GuiInstanceQueryTokens, ParserStates, GuiInstanceQueryAstInsReceiver>(&GuiInstanceQueryTokenDeleter, &GuiInstanceQueryLexerData, &GuiInstanceQueryParserData)
|
|
{
|
|
}
|
|
|
|
vl::WString Parser::GetClassName(vl::vint32_t classIndex) const
|
|
{
|
|
return vl::WString::Unmanaged(GuiInstanceQueryTypeName((GuiInstanceQueryClasses)classIndex));
|
|
}
|
|
|
|
vl::vint32_t Parser::FindCommonBaseClass(vl::vint32_t class1, vl::vint32_t class2) const
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
vl::Ptr<vl::presentation::instancequery::GuiIqQuery> Parser::ParseQueryRoot(const vl::WString& input, vl::vint codeIndex) const
|
|
{
|
|
return ParseWithString<vl::presentation::instancequery::GuiIqQuery, ParserStates::QueryRoot>(input, this, codeIndex);
|
|
}
|
|
|
|
vl::Ptr<vl::presentation::instancequery::GuiIqQuery> Parser::ParseQueryRoot(vl::collections::List<vl::regex::RegexToken>& tokens, vl::vint codeIndex) const
|
|
{
|
|
return ParseWithTokens<vl::presentation::instancequery::GuiIqQuery, ParserStates::QueryRoot>(tokens, this, codeIndex);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\INSTANCEQUERY\GENERATED\GUIINSTANCEQUERY_ASSEMBLER.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
This file is generated by: Vczh Parser Generator
|
|
From parser definition:GuiInstanceQuery
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl::presentation::instancequery
|
|
{
|
|
|
|
/***********************************************************************
|
|
GuiInstanceQueryAstInsReceiver : public vl::glr::AstInsReceiverBase
|
|
***********************************************************************/
|
|
|
|
vl::Ptr<vl::glr::ParsingAstBase> GuiInstanceQueryAstInsReceiver::CreateAstNode(vl::vint32_t type)
|
|
{
|
|
auto cppTypeName = GuiInstanceQueryCppTypeName((GuiInstanceQueryClasses)type);
|
|
switch((GuiInstanceQueryClasses)type)
|
|
{
|
|
case GuiInstanceQueryClasses::CascadeQuery:
|
|
return vl::Ptr(new vl::presentation::instancequery::GuiIqCascadeQuery);
|
|
case GuiInstanceQueryClasses::PrimaryQuery:
|
|
return vl::Ptr(new vl::presentation::instancequery::GuiIqPrimaryQuery);
|
|
case GuiInstanceQueryClasses::SetQuery:
|
|
return vl::Ptr(new vl::presentation::instancequery::GuiIqSetQuery);
|
|
default:
|
|
return vl::glr::AssemblyThrowCannotCreateAbstractType(type, cppTypeName);
|
|
}
|
|
}
|
|
|
|
void GuiInstanceQueryAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::Ptr<vl::glr::ParsingAstBase> value)
|
|
{
|
|
auto cppFieldName = GuiInstanceQueryCppFieldName((GuiInstanceQueryFields)field);
|
|
switch((GuiInstanceQueryFields)field)
|
|
{
|
|
case GuiInstanceQueryFields::CascadeQuery_child:
|
|
return vl::glr::AssemblerSetObjectField(&vl::presentation::instancequery::GuiIqCascadeQuery::child, object, field, value, cppFieldName);
|
|
case GuiInstanceQueryFields::CascadeQuery_parent:
|
|
return vl::glr::AssemblerSetObjectField(&vl::presentation::instancequery::GuiIqCascadeQuery::parent, object, field, value, cppFieldName);
|
|
case GuiInstanceQueryFields::SetQuery_first:
|
|
return vl::glr::AssemblerSetObjectField(&vl::presentation::instancequery::GuiIqSetQuery::first, object, field, value, cppFieldName);
|
|
case GuiInstanceQueryFields::SetQuery_second:
|
|
return vl::glr::AssemblerSetObjectField(&vl::presentation::instancequery::GuiIqSetQuery::second, object, field, value, cppFieldName);
|
|
default:
|
|
return vl::glr::AssemblyThrowFieldNotObject(field, cppFieldName);
|
|
}
|
|
}
|
|
|
|
void GuiInstanceQueryAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, const vl::regex::RegexToken& token, vl::vint32_t tokenIndex)
|
|
{
|
|
auto cppFieldName = GuiInstanceQueryCppFieldName((GuiInstanceQueryFields)field);
|
|
switch((GuiInstanceQueryFields)field)
|
|
{
|
|
case GuiInstanceQueryFields::PrimaryQuery_attributeName:
|
|
return vl::glr::AssemblerSetTokenField(&vl::presentation::instancequery::GuiIqPrimaryQuery::attributeName, object, field, token, tokenIndex, cppFieldName);
|
|
case GuiInstanceQueryFields::PrimaryQuery_referenceName:
|
|
return vl::glr::AssemblerSetTokenField(&vl::presentation::instancequery::GuiIqPrimaryQuery::referenceName, object, field, token, tokenIndex, cppFieldName);
|
|
case GuiInstanceQueryFields::PrimaryQuery_typeName:
|
|
return vl::glr::AssemblerSetTokenField(&vl::presentation::instancequery::GuiIqPrimaryQuery::typeName, object, field, token, tokenIndex, cppFieldName);
|
|
default:
|
|
return vl::glr::AssemblyThrowFieldNotToken(field, cppFieldName);
|
|
}
|
|
}
|
|
|
|
void GuiInstanceQueryAstInsReceiver::SetField(vl::glr::ParsingAstBase* object, vl::vint32_t field, vl::vint32_t enumItem, bool weakAssignment)
|
|
{
|
|
auto cppFieldName = GuiInstanceQueryCppFieldName((GuiInstanceQueryFields)field);
|
|
switch((GuiInstanceQueryFields)field)
|
|
{
|
|
case GuiInstanceQueryFields::PrimaryQuery_attributeNameOption:
|
|
return vl::glr::AssemblerSetEnumField(&vl::presentation::instancequery::GuiIqPrimaryQuery::attributeNameOption, object, field, enumItem, weakAssignment, cppFieldName);
|
|
case GuiInstanceQueryFields::PrimaryQuery_childOption:
|
|
return vl::glr::AssemblerSetEnumField(&vl::presentation::instancequery::GuiIqPrimaryQuery::childOption, object, field, enumItem, weakAssignment, cppFieldName);
|
|
case GuiInstanceQueryFields::PrimaryQuery_typeNameOption:
|
|
return vl::glr::AssemblerSetEnumField(&vl::presentation::instancequery::GuiIqPrimaryQuery::typeNameOption, object, field, enumItem, weakAssignment, cppFieldName);
|
|
case GuiInstanceQueryFields::SetQuery_op:
|
|
return vl::glr::AssemblerSetEnumField(&vl::presentation::instancequery::GuiIqSetQuery::op, object, field, enumItem, weakAssignment, cppFieldName);
|
|
default:
|
|
return vl::glr::AssemblyThrowFieldNotEnum(field, cppFieldName);
|
|
}
|
|
}
|
|
|
|
const wchar_t* GuiInstanceQueryTypeName(GuiInstanceQueryClasses type)
|
|
{
|
|
const wchar_t* results[] = {
|
|
L"CascadeQuery",
|
|
L"PrimaryQuery",
|
|
L"Query",
|
|
L"SetQuery",
|
|
};
|
|
vl::vint index = (vl::vint)type;
|
|
return 0 <= index && index < 4 ? results[index] : nullptr;
|
|
}
|
|
|
|
const wchar_t* GuiInstanceQueryCppTypeName(GuiInstanceQueryClasses type)
|
|
{
|
|
const wchar_t* results[] = {
|
|
L"vl::presentation::instancequery::GuiIqCascadeQuery",
|
|
L"vl::presentation::instancequery::GuiIqPrimaryQuery",
|
|
L"vl::presentation::instancequery::GuiIqQuery",
|
|
L"vl::presentation::instancequery::GuiIqSetQuery",
|
|
};
|
|
vl::vint index = (vl::vint)type;
|
|
return 0 <= index && index < 4 ? results[index] : nullptr;
|
|
}
|
|
|
|
const wchar_t* GuiInstanceQueryFieldName(GuiInstanceQueryFields field)
|
|
{
|
|
const wchar_t* results[] = {
|
|
L"CascadeQuery::child",
|
|
L"CascadeQuery::parent",
|
|
L"PrimaryQuery::attributeName",
|
|
L"PrimaryQuery::attributeNameOption",
|
|
L"PrimaryQuery::childOption",
|
|
L"PrimaryQuery::referenceName",
|
|
L"PrimaryQuery::typeName",
|
|
L"PrimaryQuery::typeNameOption",
|
|
L"SetQuery::first",
|
|
L"SetQuery::op",
|
|
L"SetQuery::second",
|
|
};
|
|
vl::vint index = (vl::vint)field;
|
|
return 0 <= index && index < 11 ? results[index] : nullptr;
|
|
}
|
|
|
|
const wchar_t* GuiInstanceQueryCppFieldName(GuiInstanceQueryFields field)
|
|
{
|
|
const wchar_t* results[] = {
|
|
L"vl::presentation::instancequery::GuiIqCascadeQuery::child",
|
|
L"vl::presentation::instancequery::GuiIqCascadeQuery::parent",
|
|
L"vl::presentation::instancequery::GuiIqPrimaryQuery::attributeName",
|
|
L"vl::presentation::instancequery::GuiIqPrimaryQuery::attributeNameOption",
|
|
L"vl::presentation::instancequery::GuiIqPrimaryQuery::childOption",
|
|
L"vl::presentation::instancequery::GuiIqPrimaryQuery::referenceName",
|
|
L"vl::presentation::instancequery::GuiIqPrimaryQuery::typeName",
|
|
L"vl::presentation::instancequery::GuiIqPrimaryQuery::typeNameOption",
|
|
L"vl::presentation::instancequery::GuiIqSetQuery::first",
|
|
L"vl::presentation::instancequery::GuiIqSetQuery::op",
|
|
L"vl::presentation::instancequery::GuiIqSetQuery::second",
|
|
};
|
|
vl::vint index = (vl::vint)field;
|
|
return 0 <= index && index < 11 ? results[index] : nullptr;
|
|
}
|
|
|
|
vl::Ptr<vl::glr::ParsingAstBase> GuiInstanceQueryAstInsReceiver::ResolveAmbiguity(vl::vint32_t type, vl::collections::Array<vl::Ptr<vl::glr::ParsingAstBase>>& candidates)
|
|
{
|
|
auto cppTypeName = GuiInstanceQueryCppTypeName((GuiInstanceQueryClasses)type);
|
|
return vl::glr::AssemblyThrowTypeNotAllowAmbiguity(type, cppTypeName);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\INSTANCEQUERY\GENERATED\GUIINSTANCEQUERY_LEXER.CPP
|
|
***********************************************************************/
|
|
/***********************************************************************
|
|
This file is generated by: Vczh Parser Generator
|
|
From parser definition:GuiInstanceQuery
|
|
Licensed under https://github.com/vczh-libraries/License
|
|
***********************************************************************/
|
|
|
|
|
|
namespace vl::presentation::instancequery
|
|
{
|
|
bool GuiInstanceQueryTokenDeleter(vl::vint token)
|
|
{
|
|
switch((GuiInstanceQueryTokens)token)
|
|
{
|
|
case GuiInstanceQueryTokens::SPACE:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const wchar_t* GuiInstanceQueryTokenId(GuiInstanceQueryTokens token)
|
|
{
|
|
static const wchar_t* results[] = {
|
|
L"INDIRECT",
|
|
L"DIRECT",
|
|
L"NAME",
|
|
L"WILDCARD_INTERSECT",
|
|
L"OPEN",
|
|
L"CLOSE",
|
|
L"XOR",
|
|
L"UNION",
|
|
L"SUBSTRACT",
|
|
L"ATTRIBUTE",
|
|
L"COLON",
|
|
L"DOT",
|
|
L"SPACE",
|
|
};
|
|
vl::vint index = (vl::vint)token;
|
|
return 0 <= index && index < GuiInstanceQueryTokenCount ? results[index] : nullptr;
|
|
}
|
|
|
|
const wchar_t* GuiInstanceQueryTokenDisplayText(GuiInstanceQueryTokens token)
|
|
{
|
|
static const wchar_t* results[] = {
|
|
L"//",
|
|
L"/",
|
|
nullptr,
|
|
L"*",
|
|
L"(",
|
|
L")",
|
|
L"^",
|
|
L"+",
|
|
L"-",
|
|
L"@",
|
|
L":",
|
|
L".",
|
|
nullptr,
|
|
};
|
|
vl::vint index = (vl::vint)token;
|
|
return 0 <= index && index < GuiInstanceQueryTokenCount ? results[index] : nullptr;
|
|
}
|
|
|
|
const wchar_t* GuiInstanceQueryTokenRegex(GuiInstanceQueryTokens token)
|
|
{
|
|
static const wchar_t* results[] = {
|
|
L"////",
|
|
L"//",
|
|
L"[a-zA-Z_][a-zA-Z0-9]*",
|
|
L"/*",
|
|
L"/(",
|
|
L"/)",
|
|
L"/^",
|
|
L"/+",
|
|
L"-",
|
|
L"@",
|
|
L":",
|
|
L".",
|
|
L"/s+",
|
|
};
|
|
vl::vint index = (vl::vint)token;
|
|
return 0 <= index && index < GuiInstanceQueryTokenCount ? results[index] : nullptr;
|
|
}
|
|
|
|
void GuiInstanceQueryLexerData(vl::stream::IStream& outputStream)
|
|
{
|
|
static const vl::vint dataLength = 232; // 1446 bytes before compressing
|
|
static const vl::vint dataBlock = 256;
|
|
static const vl::vint dataRemain = 232;
|
|
static const vl::vint dataSolidRows = 0;
|
|
static const vl::vint dataRows = 1;
|
|
static const char* compressed[] = {
|
|
"\xA6\x05\x00\x00\xE0\x00\x00\x00\x10\x00\x01\x93\x01\x84\x81\x82\x08\x82\x09\x08\x84\x8A\x0B\x84\x81\x06\x87\x04\xA0\x11\x84\x88\x14\x88\x83\x14\x17\x84\xAA\x1A\x84\x83\x15\x8E\x82\x2D\x20\x84\x8E\x13\x94\x83\x16\x93\x04\xB0\x04\x99\x14\x82\x1D\x96\x82\x40\x30\x84\x81\x24\x82\x2C\x82\x2F\x37\x84\x9F\x3A\x94\x81\x30\x82\x3D\x04\x8C\x01\xA3\xA1\x82\xA1\x80\x02\x04\x85\x04\x83\x04\x87\x00\x82\x04\x04\x8B\x04\x81\x04\x87\x7E\xAB\x7F\x0C\x81\x89\x81\x82\x04\x82\x02\x82\x5D\xDC\x95\xB7\xA4\xB5\xB2\xB3\xB3\x68\xE9\xBF\x6F\x81\x82\xB6\xB7\xB7\x70\xF1\xB2\xBF\x7E\x03\xB2\xB3\xBA\x6D\xE7\xB8\xA0\x03\xBD\xBE\xBF\xBF\x80\x81\xC2\xC3\xC4\xC5\xC2\xC3\xC3\x88\x89\xCA\xCB\xCC\xC5\xC6\xC7\xC7\x90\x91\xD2\xD3\xC8\xC7\x04\x82\xCB\x01\x98\xC0\x1A\xC4\xCD\xCE\xCF\xCF\x71\xFB\xA8\xA2\xDA\xBE\xBB\x7E\xCD\xA8\x97\xE6\xC0\xDF\xB6\x7F\x7E\x80\x05\x81\x94\xA2\xB1\x84\xA7\xA3\xA4\x5E\xCD\x8F\xAA\x81\x81\xAC\x00\xA9\x45\xB1\xF4\xC0\x06\xA0\x00",
|
|
};
|
|
vl::glr::DecompressSerializedData(compressed, true, dataSolidRows, dataRows, dataBlock, dataRemain, outputStream);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\WORKFLOWCODEGEN\GUIINSTANCELOADER_WORKFLOWCODEGEN.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
using namespace workflow::runtime;
|
|
using namespace reflection::description;
|
|
using namespace collections;
|
|
|
|
using namespace controls;
|
|
using namespace compositions;
|
|
using namespace templates;
|
|
|
|
/***********************************************************************
|
|
FindInstanceLoadingSource
|
|
***********************************************************************/
|
|
|
|
template<typename TCallback>
|
|
auto FindByTag(Ptr<GuiInstanceContext> context, GlobalStringKey namespaceName, const WString& typeName, TCallback callback)
|
|
-> std::remove_cvref_t<decltype(callback({}).Value())>
|
|
{
|
|
vint index = context->namespaces.Keys().IndexOf(namespaceName);
|
|
if (index != -1)
|
|
{
|
|
Ptr<GuiInstanceContext::NamespaceInfo> namespaceInfo = context->namespaces.Values()[index];
|
|
for (auto ns : namespaceInfo->namespaces)
|
|
{
|
|
auto fullName = GlobalStringKey::Get(ns->prefix + typeName + ns->postfix);
|
|
if (auto nullable = callback(fullName))
|
|
{
|
|
return nullable.Value();
|
|
}
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
|
|
InstanceLoadingSource FindInstanceLoadingSource(Ptr<GuiInstanceContext> context, GlobalStringKey namespaceName, const WString& typeName)
|
|
{
|
|
return FindByTag(context, namespaceName, typeName, [](GlobalStringKey fullName)->Nullable<InstanceLoadingSource>
|
|
{
|
|
if (auto loader = GetInstanceLoaderManager()->GetLoader(fullName))
|
|
{
|
|
return { { loader, fullName } };
|
|
}
|
|
return {};
|
|
});
|
|
}
|
|
|
|
Ptr<GuiResourceItem> FindInstanceResourceItem(Ptr<GuiInstanceContext> context, GuiConstructorRepr* ctor, Ptr<GuiResourceClassNameRecord> record)
|
|
{
|
|
return FindByTag(context, ctor->typeNamespace, ctor->typeName.ToString(), [=](GlobalStringKey fullName)->Nullable<Ptr<GuiResourceItem>>
|
|
{
|
|
vint index = record->classResources.Keys().IndexOf(fullName.ToString());
|
|
if (index != -1)
|
|
{
|
|
return record->classResources.Values()[index];
|
|
}
|
|
return {};
|
|
});
|
|
}
|
|
|
|
InstanceLoadingSource FindInstanceLoadingSource(Ptr<GuiInstanceContext> context, GuiConstructorRepr* ctor)
|
|
{
|
|
return FindInstanceLoadingSource(context, ctor->typeNamespace, ctor->typeName.ToString());
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_PrecompileInstanceContext
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfModule> Workflow_PrecompileInstanceContext(GuiResourcePrecompileContext& precompileContext, const WString& moduleName, types::ResolvingResult& resolvingResult, GuiResourceError::List& errors)
|
|
{
|
|
auto module = Workflow_CreateModuleWithUsings(resolvingResult.context, moduleName);
|
|
{
|
|
auto block = Workflow_InstallCtorClass(resolvingResult, module);
|
|
Workflow_GenerateCreating(precompileContext, resolvingResult, block, errors);
|
|
Workflow_GenerateBindings(precompileContext, resolvingResult, block, errors);
|
|
}
|
|
return module;
|
|
}
|
|
|
|
/***********************************************************************
|
|
WorkflowEventNamesVisitor
|
|
***********************************************************************/
|
|
|
|
class WorkflowEventNamesVisitor : public Object, public GuiValueRepr::IVisitor
|
|
{
|
|
public:
|
|
GuiResourcePrecompileContext& precompileContext;
|
|
types::ResolvingResult& resolvingResult;
|
|
List<types::PropertyResolving>& candidatePropertyTypeInfos;
|
|
Ptr<WfClassDeclaration> instanceClass;
|
|
GuiResourceError::List& errors;
|
|
|
|
IGuiInstanceLoader::TypeInfo resolvedTypeInfo;
|
|
|
|
WorkflowEventNamesVisitor(GuiResourcePrecompileContext& _precompileContext, types::ResolvingResult& _resolvingResult, List<types::PropertyResolving>& _candidatePropertyTypeInfos, Ptr<WfClassDeclaration> _instanceClass, GuiResourceError::List& _errors)
|
|
:precompileContext(_precompileContext)
|
|
, resolvingResult(_resolvingResult)
|
|
, candidatePropertyTypeInfos(_candidatePropertyTypeInfos)
|
|
, instanceClass(_instanceClass)
|
|
, errors(_errors)
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Ptr<WfDeclaration> ProcessEvent(
|
|
Ptr<GuiAttSetterRepr::EventValue> handler,
|
|
GlobalStringKey propertyName
|
|
)
|
|
{
|
|
if (auto eventInfo = resolvedTypeInfo.typeInfo->GetTypeDescriptor()->GetEventByName(propertyName.ToString(), true))
|
|
{
|
|
auto decl = Workflow_GenerateEventHandler(precompileContext, eventInfo);
|
|
decl->functionKind = WfFunctionKind::Normal;
|
|
decl->anonymity = WfFunctionAnonymity::Named;
|
|
decl->name.value = handler->value;
|
|
|
|
{
|
|
auto att = Ptr(new WfAttribute);
|
|
att->category.value = L"cpp";
|
|
att->name.value = L"Protected";
|
|
|
|
decl->attributes.Add(att);
|
|
}
|
|
{
|
|
auto att = Ptr(new WfAttribute);
|
|
att->category.value = L"cpp";
|
|
att->name.value = L"UserImpl";
|
|
|
|
decl->attributes.Add(att);
|
|
}
|
|
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
decl->statement = block;
|
|
|
|
auto stringExpr = Ptr(new WfStringExpression);
|
|
stringExpr->value.value = L"Not Implemented: " + handler->value;
|
|
|
|
auto raiseStat = Ptr(new WfRaiseExceptionStatement);
|
|
raiseStat->expression = stringExpr;
|
|
block->statements.Add(raiseStat);
|
|
}
|
|
return decl;
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, handler->attPosition,
|
|
L"Precompile: Event \"" +
|
|
propertyName.ToString() +
|
|
L"\" cannot be found in type \"" +
|
|
resolvedTypeInfo.typeName.ToString() +
|
|
L"\"."));
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Visit(GuiTextRepr* repr)override
|
|
{
|
|
}
|
|
|
|
void Visit(GuiAttSetterRepr* repr)override
|
|
{
|
|
for (auto [setter, index] : indexed(repr->setters.Values()))
|
|
{
|
|
auto loader = GetInstanceLoaderManager()->GetLoader(resolvedTypeInfo.typeName);
|
|
List<types::PropertyResolving> possibleInfos;
|
|
auto prop = repr->setters.Keys()[index];
|
|
|
|
WString errorPrefix;
|
|
if (Workflow_GetPropertyTypes(precompileContext, errorPrefix, resolvingResult, loader, resolvedTypeInfo, prop, setter, possibleInfos, errors))
|
|
{
|
|
if (setter->binding == GlobalStringKey::_Set)
|
|
{
|
|
if (possibleInfos[0].info->support == GuiInstancePropertyInfo::SupportSet)
|
|
{
|
|
auto setTarget = dynamic_cast<GuiAttSetterRepr*>(setter->values[0].Obj());
|
|
|
|
List<types::PropertyResolving> infos;
|
|
WorkflowEventNamesVisitor visitor(precompileContext, resolvingResult, infos, instanceClass, errors);
|
|
auto typeInfo = possibleInfos[0].info->acceptableTypes[0];
|
|
visitor.resolvedTypeInfo.typeName = GlobalStringKey::Get(typeInfo->GetTypeDescriptor()->GetTypeName());
|
|
visitor.resolvedTypeInfo.typeInfo = typeInfo;
|
|
setTarget->Accept(&visitor);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition, errorPrefix + L" does not support the \"-set\" binding."));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (auto value : setter->values)
|
|
{
|
|
WorkflowEventNamesVisitor visitor(precompileContext, resolvingResult, possibleInfos, instanceClass, errors);
|
|
value->Accept(&visitor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto [handler, index] : indexed(repr->eventHandlers.Values()))
|
|
{
|
|
if (handler->binding == GlobalStringKey::Empty)
|
|
{
|
|
auto propertyName = repr->eventHandlers.Keys()[index];
|
|
if (auto decl = ProcessEvent(handler, propertyName))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, handler->valuePosition, decl);
|
|
instanceClass->declarations.Add(decl);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Visit(GuiConstructorRepr* repr)override
|
|
{
|
|
auto context = resolvingResult.context;
|
|
|
|
bool inferType = repr->typeNamespace == GlobalStringKey::Empty&&repr->typeName == GlobalStringKey::_InferType;
|
|
|
|
bool noContextToInfer = false;
|
|
if (inferType)
|
|
{
|
|
if (candidatePropertyTypeInfos.Count() == 1)
|
|
{
|
|
auto info = candidatePropertyTypeInfos[0].info;
|
|
if (info->acceptableTypes.Count() == 1)
|
|
{
|
|
auto typeInfo = info->acceptableTypes[0];
|
|
resolvedTypeInfo.typeName = GlobalStringKey::Get(typeInfo->GetTypeDescriptor()->GetTypeName());
|
|
resolvedTypeInfo.typeInfo = typeInfo;
|
|
}
|
|
else if (info->acceptableTypes.Count() == 0)
|
|
{
|
|
noContextToInfer = true;
|
|
}
|
|
}
|
|
else if (candidatePropertyTypeInfos.Count() == 0)
|
|
{
|
|
noContextToInfer = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (repr == context->instance.Obj())
|
|
{
|
|
auto fullName = GlobalStringKey::Get(context->className);
|
|
if (auto reprType = GetInstanceLoaderManager()->GetTypeInfoForType(fullName))
|
|
{
|
|
resolvedTypeInfo.typeName = fullName;
|
|
resolvedTypeInfo.typeInfo = reprType;
|
|
}
|
|
}
|
|
if (!resolvedTypeInfo.typeInfo)
|
|
{
|
|
auto source = FindInstanceLoadingSource(context, repr);
|
|
resolvedTypeInfo.typeName = source.typeName;
|
|
resolvedTypeInfo.typeInfo = GetInstanceLoaderManager()->GetTypeInfoForType(source.typeName);
|
|
}
|
|
}
|
|
|
|
if (resolvedTypeInfo.typeInfo)
|
|
{
|
|
if (repr->setters.Count() == 1 && repr->setters.Keys()[0] == GlobalStringKey::Empty)
|
|
{
|
|
auto setter = repr->setters.Values()[0];
|
|
if (setter->values.Count() == 1)
|
|
{
|
|
if (auto text = setter->values[0].Cast<GuiTextRepr>())
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
Visit((GuiAttSetterRepr*)repr);
|
|
}
|
|
else if (inferType)
|
|
{
|
|
if (noContextToInfer)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"Precompile: Unable to resolve type \"_\" without any context."));
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"Precompile: Unable to resolve type \"_\" since the current property accepts multiple types."));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"Precompile: Failed to find type \"" +
|
|
(repr->typeNamespace == GlobalStringKey::Empty
|
|
? repr->typeName.ToString()
|
|
: repr->typeNamespace.ToString() + L":" + repr->typeName.ToString()
|
|
) +
|
|
L"\"."));
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
Workflow_GenerateInstanceClass
|
|
***********************************************************************/
|
|
|
|
class ReplaceDeclImplVisitor
|
|
: public workflow::empty_visitor::DeclarationVisitor
|
|
, public workflow::empty_visitor::VirtualCfeDeclarationVisitor
|
|
, public workflow::empty_visitor::VirtualCseDeclarationVisitor
|
|
{
|
|
public:
|
|
Func<Ptr<WfStatement>()> statCtor;
|
|
List<Ptr<WfDeclaration>>& unprocessed;
|
|
|
|
ReplaceDeclImplVisitor(Func<Ptr<WfStatement>()> _statCtor, List<Ptr<WfDeclaration>>& _unprocessed)
|
|
:statCtor(_statCtor)
|
|
, unprocessed(_unprocessed)
|
|
{
|
|
}
|
|
|
|
void Dispatch(WfVirtualCfeDeclaration* node)override
|
|
{
|
|
node->Accept(static_cast<WfVirtualCfeDeclaration::IVisitor*>(this));
|
|
}
|
|
|
|
void Dispatch(WfVirtualCseDeclaration* node)override
|
|
{
|
|
node->Accept(static_cast<WfVirtualCseDeclaration::IVisitor*>(this));
|
|
}
|
|
|
|
void Visit(WfFunctionDeclaration* node)override
|
|
{
|
|
node->statement = statCtor();
|
|
}
|
|
|
|
void Visit(WfConstructorDeclaration* node)override
|
|
{
|
|
node->statement = statCtor();
|
|
}
|
|
|
|
void Visit(WfDestructorDeclaration* node)override
|
|
{
|
|
node->statement = statCtor();
|
|
}
|
|
|
|
void Visit(WfClassDeclaration* node)override
|
|
{
|
|
CopyFrom(unprocessed, node->declarations, true);
|
|
}
|
|
};
|
|
|
|
Ptr<workflow::WfModule> Workflow_GenerateInstanceClass(GuiResourcePrecompileContext& precompileContext, const WString& moduleName, types::ResolvingResult& resolvingResult, GuiResourceError::List& errors, vint passIndex)
|
|
{
|
|
bool needFunctionBody = false;
|
|
bool needEventHandler = false;
|
|
switch (passIndex)
|
|
{
|
|
case IGuiResourceTypeResolver_Precompile::Instance_CollectInstanceTypes:
|
|
needFunctionBody = false;
|
|
needEventHandler = false;
|
|
break;
|
|
case IGuiResourceTypeResolver_Precompile::Instance_CollectEventHandlers:
|
|
needFunctionBody = false;
|
|
needEventHandler = true;
|
|
break;
|
|
case IGuiResourceTypeResolver_Precompile::Instance_GenerateInstanceClass:
|
|
needFunctionBody = true;
|
|
needEventHandler = true;
|
|
break;
|
|
}
|
|
auto classNameRecord = precompileContext.targetFolder->GetValueByPath(L"ClassNameRecord").Cast<GuiResourceClassNameRecord>();
|
|
|
|
Ptr<ITypeInfo> baseType;
|
|
Ptr<GuiResourceItem> baseTypeResourceItem;
|
|
Ptr<GuiInstanceContext> baseTypeContext;
|
|
Ptr<WfType> baseWfType;
|
|
auto context = resolvingResult.context;
|
|
{
|
|
auto source = FindInstanceLoadingSource(context, context->instance.Obj());
|
|
baseType = GetInstanceLoaderManager()->GetTypeInfoForType(source.typeName);
|
|
if (!baseType)
|
|
{
|
|
baseTypeResourceItem = FindInstanceResourceItem(context, context->instance.Obj(), classNameRecord);
|
|
}
|
|
if (!baseType && !baseTypeResourceItem)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, context->instance->tagPosition,
|
|
L"Precompile: Failed to find type \"" +
|
|
(context->instance->typeNamespace == GlobalStringKey::Empty
|
|
? context->instance->typeName.ToString()
|
|
: context->instance->typeNamespace.ToString() + L":" + context->instance->typeName.ToString()
|
|
) +
|
|
L"\"."));
|
|
return nullptr;
|
|
}
|
|
if (baseTypeResourceItem && needEventHandler)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, context->instance->tagPosition,
|
|
L"[INTERNAL ERROR] Precompile: Failed to find compiled type in previous passes \"" +
|
|
(context->instance->typeNamespace == GlobalStringKey::Empty
|
|
? context->instance->typeName.ToString()
|
|
: context->instance->typeNamespace.ToString() + L":" + context->instance->typeName.ToString()
|
|
) +
|
|
L"\"."));
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
if (baseTypeResourceItem)
|
|
{
|
|
baseTypeContext = baseTypeResourceItem->GetContent().Cast<GuiInstanceContext>();
|
|
|
|
List<WString> fragments;
|
|
SplitTypeName(baseTypeContext->className, fragments);
|
|
for (vint i = 0; i < fragments.Count(); i++)
|
|
{
|
|
if (baseWfType)
|
|
{
|
|
auto type = Ptr(new WfChildType);
|
|
type->parent = baseWfType;
|
|
type->name.value = fragments[i];
|
|
baseWfType = type;
|
|
}
|
|
else
|
|
{
|
|
auto type = Ptr(new WfTopQualifiedType);
|
|
type->name.value = fragments[i];
|
|
baseWfType = type;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Instance Class
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
auto module = Workflow_CreateModuleWithUsings(context, moduleName);
|
|
auto instanceClass = Workflow_InstallClass(context->className, module);
|
|
{
|
|
if (baseWfType)
|
|
{
|
|
instanceClass->baseTypes.Add(baseWfType);
|
|
}
|
|
else
|
|
{
|
|
auto typeInfo = Ptr(new TypeDescriptorTypeInfo(baseType->GetTypeDescriptor(), TypeInfoHint::Normal));
|
|
auto baseType = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
instanceClass->baseTypes.Add(baseType);
|
|
}
|
|
|
|
if (context->codeBehind)
|
|
{
|
|
auto value = Ptr(new WfStringExpression);
|
|
value->value.value = instanceClass->name.value;
|
|
|
|
auto att = Ptr(new WfAttribute);
|
|
att->category.value = L"cpp";
|
|
att->name.value = L"File";
|
|
att->value = value;
|
|
|
|
instanceClass->attributes.Add(att);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Inherit from Constructor Class
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
if (needFunctionBody)
|
|
{
|
|
auto baseConstructorType = Ptr(new WfReferenceType);
|
|
baseConstructorType->name.value = instanceClass->name.value + L"Constructor";
|
|
instanceClass->baseTypes.Add(baseConstructorType);
|
|
|
|
{
|
|
auto value = Ptr(new WfTypeOfTypeExpression);
|
|
value->type = CopyType(baseConstructorType);
|
|
|
|
auto att = Ptr(new WfAttribute);
|
|
att->category.value = L"cpp";
|
|
att->name.value = L"Friend";
|
|
att->value = value;
|
|
|
|
instanceClass->attributes.Add(att);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Helpers
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
auto parseClassMembers = [&](const WString& code, const WString& name, List<Ptr<WfDeclaration>>& memberDecls, GuiResourceTextPos position)
|
|
{
|
|
WString wrappedCode = L"module parse_members; class Class {\r\n" + code + L"\r\n}";
|
|
if (auto module = Workflow_ParseModule(precompileContext, { resolvingResult.resource }, wrappedCode, position, errors, { 1,0 }))
|
|
{
|
|
CopyFrom(memberDecls, module->declarations[0].Cast<WfClassDeclaration>()->declarations);
|
|
}
|
|
};
|
|
|
|
auto notImplemented = []()
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
auto stringExpr = Ptr(new WfStringExpression);
|
|
stringExpr->value.value = L"Not Implemented";
|
|
|
|
auto raiseStat = Ptr(new WfRaiseExceptionStatement);
|
|
raiseStat->expression = stringExpr;
|
|
|
|
block->statements.Add(raiseStat);
|
|
return block;
|
|
};
|
|
|
|
auto getDefaultType = [&](const WString& className)->Tuple<Ptr<ITypeInfo>, WString>
|
|
{
|
|
auto paramTd = GetTypeDescriptor(className);
|
|
if (!paramTd)
|
|
{
|
|
auto source = FindInstanceLoadingSource(resolvingResult.context, {}, className);
|
|
if (auto typeInfo = GetInstanceLoaderManager()->GetTypeInfoForType(source.typeName))
|
|
{
|
|
paramTd = typeInfo->GetTypeDescriptor();
|
|
}
|
|
}
|
|
|
|
if (paramTd)
|
|
{
|
|
auto typeInfo = Workflow_GetSuggestedParameterType(precompileContext, paramTd);
|
|
switch (typeInfo->GetDecorator())
|
|
{
|
|
case ITypeInfo::RawPtr: return { typeInfo,className + L"*" };
|
|
case ITypeInfo::SharedPtr: return { typeInfo,className + L"^" };
|
|
default: return { typeInfo,className };
|
|
}
|
|
}
|
|
return { nullptr,className };
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// ref.Members
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
if (context->memberScript != L"")
|
|
{
|
|
List<Ptr<WfDeclaration>> memberDecls;
|
|
parseClassMembers(context->memberScript, L"members of instance \"" + context->className + L"\"", memberDecls, context->memberPosition);
|
|
|
|
if (!needFunctionBody)
|
|
{
|
|
List<Ptr<WfDeclaration>> unprocessed;
|
|
CopyFrom(unprocessed, memberDecls);
|
|
|
|
ReplaceDeclImplVisitor visitor(notImplemented, unprocessed);
|
|
for (vint i = 0; i < unprocessed.Count(); i++)
|
|
{
|
|
unprocessed[i]->Accept(&visitor);
|
|
}
|
|
}
|
|
|
|
CopyFrom(instanceClass->declarations, memberDecls, true);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Constructor Declaration
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
auto ctor = Ptr(new WfConstructorDeclaration);
|
|
ctor->constructorType = WfConstructorType::RawPtr;
|
|
auto ctorBlock = (!needFunctionBody ? notImplemented() : Ptr(new WfBlockStatement));
|
|
ctor->statement = ctorBlock;
|
|
|
|
if (baseWfType)
|
|
{
|
|
auto call = Ptr(new WfBaseConstructorCall);
|
|
ctor->baseConstructorCalls.Add(call);
|
|
call->type = CopyType(instanceClass->baseTypes[0]);
|
|
baseTypeContext = baseTypeResourceItem->GetContent().Cast<GuiInstanceContext>();
|
|
|
|
for (auto parameter : baseTypeContext->parameters)
|
|
{
|
|
auto parameterTypeInfoTuple = getDefaultType(parameter->className.ToString());
|
|
auto expression = Workflow_ParseExpression(
|
|
precompileContext,
|
|
parameter->classPosition.originalLocation,
|
|
L"cast("+parameterTypeInfoTuple.get<1>() + L") (null of object)",
|
|
parameter->classPosition,
|
|
errors,
|
|
{ 0,5 }
|
|
);
|
|
if (!expression)
|
|
{
|
|
auto nullExpr = Ptr(new WfLiteralExpression);
|
|
nullExpr->value = WfLiteralValue::Null;
|
|
expression = nullExpr;
|
|
}
|
|
call->arguments.Add(expression);
|
|
}
|
|
}
|
|
else if (auto group = baseType->GetTypeDescriptor()->GetConstructorGroup())
|
|
{
|
|
auto ctorInfo = group->GetMethod(0);
|
|
vint count = ctorInfo->GetParameterCount();
|
|
if (count > 0)
|
|
{
|
|
if (needFunctionBody)
|
|
{
|
|
if (auto call = resolvingResult.rootLoader->CreateRootInstance(precompileContext, resolvingResult, resolvingResult.rootTypeInfo, resolvingResult.rootCtorArguments, errors))
|
|
{
|
|
ctor->baseConstructorCalls.Add(call);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
auto call = Ptr(new WfBaseConstructorCall);
|
|
ctor->baseConstructorCalls.Add(call);
|
|
|
|
call->type = CopyType(instanceClass->baseTypes[0]);
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
call->arguments.Add(CreateDefaultValue(ctorInfo->GetParameter(i)->GetType()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// ref.LocalizedString (Property)
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
for (auto localized : context->localizeds)
|
|
{
|
|
if (auto lsTd = GetTypeDescriptor(localized->className.ToString()))
|
|
{
|
|
ITypeDescriptor* lsiTd = nullptr;
|
|
if (auto group = lsTd->GetMethodGroupByName(L"Get", false))
|
|
{
|
|
vint count = group->GetMethodCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto method = group->GetMethod(i);
|
|
if (method->GetParameterCount() == 1)
|
|
{
|
|
auto paramTd = method->GetParameter(0)->GetType()->GetTypeDescriptor();
|
|
if (paramTd == description::GetTypeDescriptor<Locale>())
|
|
{
|
|
lsiTd = method->GetReturn()->GetTypeDescriptor();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lsiTd)
|
|
{
|
|
auto prop = Ptr(new WfAutoPropertyDeclaration);
|
|
instanceClass->declarations.Add(prop);
|
|
|
|
prop->functionKind = WfFunctionKind::Normal;
|
|
prop->name.value = localized->name.ToString();
|
|
prop->type = GetTypeFromTypeInfo(Workflow_GetSuggestedParameterType(precompileContext, lsiTd).Obj());
|
|
prop->configConst = WfAPConst::Writable;
|
|
prop->configObserve = WfAPObserve::Observable;
|
|
|
|
auto localeNameExpr = Ptr(new WfStringExpression);
|
|
localeNameExpr->value.value = L"en-US";
|
|
|
|
auto defaultLocalExpr = Ptr(new WfTypeCastingExpression);
|
|
defaultLocalExpr->strategy = WfTypeCastingStrategy::Strong;
|
|
defaultLocalExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<Locale>::CreateTypeInfo().Obj());
|
|
defaultLocalExpr->expression = localeNameExpr;
|
|
|
|
auto getExpr = Ptr(new WfChildExpression);
|
|
getExpr->parent = GetExpressionFromTypeDescriptor(lsTd);
|
|
getExpr->name.value = L"Get";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = getExpr;
|
|
callExpr->arguments.Add(defaultLocalExpr);
|
|
prop->expression = callExpr;
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, localized->classPosition,
|
|
L"Precompile: Class \"" +
|
|
localized->className.ToString() +
|
|
L"\" of localized strings \"" +
|
|
localized->name.ToString() +
|
|
L"\" is not a correct localized strings class."));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, localized->classPosition,
|
|
L"Precompile: Class \"" +
|
|
localized->className.ToString() +
|
|
L"\" of localized strings \"" +
|
|
localized->name.ToString() +
|
|
L"\" cannot be found."));
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// ref.Parameter (Variable, Getter, CtorArgument)
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
for (auto parameter : context->parameters)
|
|
{
|
|
auto parameterTypeInfoTuple = getDefaultType(parameter->className.ToString());
|
|
vint errorCount = errors.Count();
|
|
auto type = Workflow_ParseType(precompileContext, { resolvingResult.resource }, parameterTypeInfoTuple.get<1>(), parameter->classPosition, errors);
|
|
|
|
if (!needFunctionBody && !parameterTypeInfoTuple.get<0>() && errorCount == errors.Count())
|
|
{
|
|
if (!type || type.Cast<WfReferenceType>() || type.Cast<WfChildType>() || type.Cast<WfTopQualifiedType>())
|
|
{
|
|
type = Workflow_ParseType(precompileContext, { resolvingResult.resource }, parameter->className.ToString() + L"*", parameter->classPosition, errors);
|
|
}
|
|
}
|
|
if (type)
|
|
{
|
|
if (needFunctionBody)
|
|
{
|
|
auto decl = Ptr(new WfVariableDeclaration);
|
|
instanceClass->declarations.Add(decl);
|
|
|
|
decl->name.value = L"<parameter>" + parameter->name.ToString();
|
|
decl->type = CopyType(type);
|
|
decl->expression = CreateDefaultValue(parameterTypeInfoTuple.get<0>().Obj());
|
|
|
|
Workflow_RecordScriptPosition(precompileContext, parameter->tagPosition, (Ptr<WfDeclaration>)decl);
|
|
}
|
|
{
|
|
auto decl = Ptr(new WfFunctionDeclaration);
|
|
instanceClass->declarations.Add(decl);
|
|
|
|
decl->functionKind = WfFunctionKind::Normal;
|
|
decl->anonymity = WfFunctionAnonymity::Named;
|
|
decl->name.value = L"Get" + parameter->name.ToString();
|
|
decl->returnType = CopyType(type);
|
|
if (needFunctionBody)
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
decl->statement = block;
|
|
|
|
auto ref = Ptr(new WfReferenceExpression);
|
|
ref->name.value = L"<parameter>" + parameter->name.ToString();
|
|
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
returnStat->expression = ref;
|
|
block->statements.Add(returnStat);
|
|
}
|
|
else
|
|
{
|
|
decl->statement = notImplemented();
|
|
}
|
|
|
|
Workflow_RecordScriptPosition(precompileContext, parameter->tagPosition, (Ptr<WfDeclaration>)decl);
|
|
}
|
|
{
|
|
auto decl = Ptr(new WfPropertyDeclaration);
|
|
instanceClass->declarations.Add(decl);
|
|
|
|
decl->name.value = parameter->name.ToString();
|
|
decl->type = type;
|
|
decl->getter.value = L"Get" + parameter->name.ToString();
|
|
|
|
Workflow_RecordScriptPosition(precompileContext, parameter->tagPosition, (Ptr<WfDeclaration>)decl);
|
|
}
|
|
{
|
|
auto argument = Ptr(new WfFunctionArgument);
|
|
argument->name.value = L"<ctor-parameter>" + parameter->name.ToString();
|
|
argument->type = CopyType(type);
|
|
ctor->arguments.Add(argument);
|
|
}
|
|
if (needFunctionBody)
|
|
{
|
|
auto refLeft = Ptr(new WfReferenceExpression);
|
|
refLeft->name.value = L"<parameter>" + parameter->name.ToString();
|
|
|
|
auto refRight = Ptr(new WfReferenceExpression);
|
|
refRight->name.value = L"<ctor-parameter>" + parameter->name.ToString();
|
|
|
|
auto assignExpr = Ptr(new WfBinaryExpression);
|
|
assignExpr->op = WfBinaryOperator::Assign;
|
|
assignExpr->first = refLeft;
|
|
assignExpr->second = refRight;
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = assignExpr;
|
|
|
|
ctorBlock->statements.Add(exprStat);
|
|
|
|
Workflow_RecordScriptPosition(precompileContext, parameter->tagPosition, (Ptr<WfStatement>)exprStat);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Event Handlers
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
if (needEventHandler)
|
|
{
|
|
List<types::PropertyResolving> infos;
|
|
WorkflowEventNamesVisitor visitor(precompileContext, resolvingResult, infos, instanceClass, errors);
|
|
context->instance->Accept(&visitor);
|
|
}
|
|
|
|
instanceClass->declarations.Add(ctor);
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Calling Constructor Class
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
if (needFunctionBody)
|
|
{
|
|
{
|
|
auto getRmExpr = Ptr(new WfChildExpression);
|
|
getRmExpr->parent = GetExpressionFromTypeDescriptor(description::GetTypeDescriptor<IGuiResourceManager>());
|
|
getRmExpr->name.value = L"GetResourceManager";
|
|
|
|
auto call1Expr = Ptr(new WfCallExpression);
|
|
call1Expr->function = getRmExpr;
|
|
|
|
auto getResExpr = Ptr(new WfMemberExpression);
|
|
getResExpr->parent = call1Expr;
|
|
getResExpr->name.value = L"GetResourceFromClassName";
|
|
|
|
auto classNameExpr = Ptr(new WfStringExpression);
|
|
classNameExpr->value.value = context->className;
|
|
|
|
auto call2Expr = Ptr(new WfCallExpression);
|
|
call2Expr->function = getResExpr;
|
|
call2Expr->arguments.Add(classNameExpr);
|
|
|
|
auto varDecl = Ptr(new WfVariableDeclaration);
|
|
varDecl->name.value = L"<resource>";
|
|
varDecl->expression = call2Expr;
|
|
|
|
auto varStat = Ptr(new WfVariableStatement);
|
|
varStat->variable = varDecl;
|
|
|
|
ctorBlock->statements.Add(varStat);
|
|
}
|
|
{
|
|
auto resRef = Ptr(new WfReferenceExpression);
|
|
resRef->name.value = L"<resource>";
|
|
|
|
auto resRef2 = Ptr(new WfReferenceExpression);
|
|
resRef2->name.value = L"<resource>";
|
|
|
|
auto wdRef = Ptr(new WfMemberExpression);
|
|
wdRef->parent = resRef2;
|
|
wdRef->name.value = L"WorkingDirectory";
|
|
|
|
auto newClassExpr = Ptr(new WfNewClassExpression);
|
|
newClassExpr->type = GetTypeFromTypeInfo(TypeInfoRetriver<Ptr<GuiResourcePathResolver>>::CreateTypeInfo().Obj());
|
|
newClassExpr->arguments.Add(resRef);
|
|
newClassExpr->arguments.Add(wdRef);
|
|
|
|
auto varDecl = Ptr(new WfVariableDeclaration);
|
|
varDecl->name.value = L"<resolver>";
|
|
varDecl->expression = newClassExpr;
|
|
|
|
auto varStat = Ptr(new WfVariableStatement);
|
|
varStat->variable = varDecl;
|
|
|
|
ctorBlock->statements.Add(varStat);
|
|
}
|
|
{
|
|
auto setRef = Ptr(new WfMemberExpression);
|
|
setRef->parent = Ptr(new WfThisExpression);
|
|
setRef->name.value = L"SetResourceResolver";
|
|
|
|
auto resolverRef = Ptr(new WfReferenceExpression);
|
|
resolverRef->name.value = L"<resolver>";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = setRef;
|
|
callExpr->arguments.Add(resolverRef);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = callExpr;
|
|
|
|
ctorBlock->statements.Add(stat);
|
|
}
|
|
{
|
|
auto initRef = Ptr(new WfMemberExpression);
|
|
initRef->parent = Ptr(new WfThisExpression);
|
|
{
|
|
List<WString> fragments;
|
|
SplitTypeName(resolvingResult.context->className, fragments);
|
|
initRef->name.value = L"<" + From(fragments).Aggregate([](const WString& a, const WString& b) {return a + L"-" + b; }) + L">Initialize";
|
|
}
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = initRef;
|
|
callExpr->arguments.Add(Ptr(new WfThisExpression));
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = callExpr;
|
|
|
|
ctorBlock->statements.Add(stat);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// ref.Ctor
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
if (context->ctorScript != L"")
|
|
{
|
|
if (auto stat = Workflow_ParseStatement(precompileContext, { resolvingResult.resource }, context->ctorScript, context->ctorPosition, errors))
|
|
{
|
|
if (needFunctionBody)
|
|
{
|
|
if (!stat.Cast<WfBlockStatement>())
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
block->statements.Add(stat);
|
|
stat = block;
|
|
}
|
|
|
|
auto decl = Ptr(new WfFunctionDeclaration);
|
|
decl->functionKind = WfFunctionKind::Normal;
|
|
decl->anonymity = WfFunctionAnonymity::Named;
|
|
decl->name.value = L"<instance-ctor>";
|
|
decl->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<void>::CreateTypeInfo().Obj());
|
|
decl->statement = stat;
|
|
instanceClass->declarations.Add(decl);
|
|
|
|
{
|
|
auto refCtor = Ptr(new WfReferenceExpression);
|
|
refCtor->name.value = L"<instance-ctor>";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refCtor;
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = callExpr;
|
|
ctorBlock->statements.Add(exprStat);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Destructor
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
auto dtor = Ptr(new WfDestructorDeclaration);
|
|
auto dtorBlock = Ptr(new WfBlockStatement);
|
|
dtor->statement = dtorBlock;
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// ref.Dtor
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
if (context->dtorScript != L"")
|
|
{
|
|
if (auto stat = Workflow_ParseStatement(precompileContext, { resolvingResult.resource }, context->dtorScript, context->dtorPosition, errors))
|
|
{
|
|
if (needFunctionBody)
|
|
{
|
|
if (!stat.Cast<WfBlockStatement>())
|
|
{
|
|
auto block = Ptr(new WfBlockStatement);
|
|
block->statements.Add(stat);
|
|
stat = block;
|
|
}
|
|
|
|
auto decl = Ptr(new WfFunctionDeclaration);
|
|
decl->functionKind = WfFunctionKind::Normal;
|
|
decl->anonymity = WfFunctionAnonymity::Named;
|
|
decl->name.value = L"<instance-dtor>";
|
|
decl->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<void>::CreateTypeInfo().Obj());
|
|
decl->statement = stat;
|
|
instanceClass->declarations.Add(decl);
|
|
|
|
{
|
|
auto refDtor = Ptr(new WfReferenceExpression);
|
|
refDtor->name.value = L"<instance-dtor>";
|
|
|
|
auto callExpr = Ptr(new WfCallExpression);
|
|
callExpr->function = refDtor;
|
|
|
|
auto exprStat = Ptr(new WfExpressionStatement);
|
|
exprStat->expression = callExpr;
|
|
dtorBlock->statements.Add(exprStat);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////
|
|
// Clear Binding Subscriptions
|
|
///////////////////////////////////////////////////////////////
|
|
|
|
{
|
|
auto ref = Ptr(new WfReferenceExpression);
|
|
ref->name.value = L"FinalizeGeneralInstance";
|
|
|
|
Ptr<WfExpression> thisExpr = Ptr(new WfThisExpression);
|
|
ITypeDescriptor* types[] =
|
|
{
|
|
description::GetTypeDescriptor<GuiTemplate>(),
|
|
description::GetTypeDescriptor<GuiCustomControl>(),
|
|
description::GetTypeDescriptor<GuiControlHost>(),
|
|
};
|
|
|
|
if (!baseType)
|
|
{
|
|
auto currentContext = context;
|
|
while (!baseType)
|
|
{
|
|
auto item = FindInstanceResourceItem(currentContext, currentContext->instance.Obj(), classNameRecord);
|
|
if (!item) break;
|
|
|
|
currentContext = item->GetContent().Cast<GuiInstanceContext>();
|
|
auto source = FindInstanceLoadingSource(currentContext, currentContext->instance.Obj());
|
|
baseType = GetInstanceLoaderManager()->GetTypeInfoForType(source.typeName);
|
|
}
|
|
}
|
|
|
|
if (baseType)
|
|
{
|
|
for (auto td : types)
|
|
{
|
|
if (baseType->GetTypeDescriptor()->CanConvertTo(td))
|
|
{
|
|
ref->name.value = L"FinalizeInstanceRecursively";
|
|
|
|
Ptr<ITypeInfo> typeInfo = Ptr(new TypeDescriptorTypeInfo(td, TypeInfoHint::Normal));
|
|
typeInfo = Ptr(new RawPtrTypeInfo(typeInfo));
|
|
|
|
auto inferExpr = Ptr(new WfInferExpression);
|
|
inferExpr->type = GetTypeFromTypeInfo(typeInfo.Obj());
|
|
inferExpr->expression = thisExpr;
|
|
thisExpr = inferExpr;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = ref;
|
|
call->arguments.Add(thisExpr);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
dtorBlock->statements.Add(stat);
|
|
}
|
|
|
|
instanceClass->declarations.Add(dtor);
|
|
|
|
return module;
|
|
}
|
|
|
|
/***********************************************************************
|
|
GuiWorkflowSharedManagerPlugin
|
|
***********************************************************************/
|
|
|
|
#undef ERROR_CODE_PREFIX
|
|
|
|
class GuiWorkflowSharedManagerPlugin;
|
|
GuiWorkflowSharedManagerPlugin* sharedManagerPlugin = 0;
|
|
|
|
class GuiWorkflowSharedManagerPlugin : public Object, public IGuiPlugin
|
|
{
|
|
protected:
|
|
workflow::Parser workflowParser;
|
|
Ptr<WfLexicalScopeManager> workflowManager;
|
|
|
|
public:
|
|
|
|
GUI_PLUGIN_NAME(GacUI_Compiler_WorkflowSharedManager)
|
|
{
|
|
}
|
|
|
|
void Load()override
|
|
{
|
|
sharedManagerPlugin = this;
|
|
}
|
|
|
|
void Unload()override
|
|
{
|
|
sharedManagerPlugin = 0;
|
|
}
|
|
|
|
WfLexicalScopeManager* GetWorkflowManager(GuiResourceCpuArchitecture targetCpuArchitecture)
|
|
{
|
|
WfCpuArchitecture wfCpuArchitecture = WfCpuArchitecture::AsExecutable;
|
|
switch (targetCpuArchitecture)
|
|
{
|
|
case GuiResourceCpuArchitecture::x86:
|
|
wfCpuArchitecture = WfCpuArchitecture::x86;
|
|
break;
|
|
case GuiResourceCpuArchitecture::x64:
|
|
wfCpuArchitecture = WfCpuArchitecture::x64;
|
|
break;
|
|
default:
|
|
CHECK_FAIL(L"The target CPU architecture is unspecified.");
|
|
}
|
|
|
|
if (!workflowManager)
|
|
{
|
|
workflowManager = Ptr(new WfLexicalScopeManager(workflowParser, wfCpuArchitecture));
|
|
}
|
|
else
|
|
{
|
|
CHECK_ERROR(workflowManager->cpuArchitecture == wfCpuArchitecture, L"The target CPU architecture cannot be changed.");
|
|
}
|
|
return workflowManager.Obj();
|
|
}
|
|
|
|
Ptr<WfLexicalScopeManager> TransferWorkflowManager()
|
|
{
|
|
auto result = workflowManager;
|
|
workflowManager = nullptr;
|
|
return result;
|
|
}
|
|
};
|
|
GUI_REGISTER_PLUGIN(GuiWorkflowSharedManagerPlugin)
|
|
|
|
WfLexicalScopeManager* Workflow_GetSharedManager(GuiResourceCpuArchitecture targetCpuArchitecture)
|
|
{
|
|
return sharedManagerPlugin->GetWorkflowManager(targetCpuArchitecture);
|
|
}
|
|
|
|
Ptr<WfLexicalScopeManager> Workflow_TransferSharedManager()
|
|
{
|
|
return sharedManagerPlugin->TransferWorkflowManager();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\WORKFLOWCODEGEN\GUIINSTANCELOADER_WORKFLOWCOLLECTREFERENCES.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace reflection::description;
|
|
using namespace collections;
|
|
using namespace workflow::analyzer;
|
|
|
|
/***********************************************************************
|
|
Workflow_AdjustPropertySearchType
|
|
***********************************************************************/
|
|
|
|
IGuiInstanceLoader::TypeInfo Workflow_AdjustPropertySearchType(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, IGuiInstanceLoader::TypeInfo resolvedTypeInfo, GlobalStringKey prop)
|
|
{
|
|
if (resolvedTypeInfo.typeName.ToString() == resolvingResult.context->className)
|
|
{
|
|
if (auto propTd = resolvedTypeInfo.typeInfo->GetTypeDescriptor())
|
|
{
|
|
vint baseCount = propTd->GetBaseTypeDescriptorCount();
|
|
for (vint i = 0; i < baseCount; i++)
|
|
{
|
|
auto baseTd = propTd->GetBaseTypeDescriptor(i);
|
|
if (auto ctorGroup = baseTd->GetConstructorGroup())
|
|
{
|
|
if (ctorGroup->GetMethodCount() == 1)
|
|
{
|
|
auto ctor = ctorGroup->GetMethod(0);
|
|
auto propertyName = prop.ToString();
|
|
auto ctorArgumentName = L"<ctor-parameter>" + propertyName;
|
|
vint paramCount = ctor->GetParameterCount();
|
|
for (vint j = 0; j < paramCount; j++)
|
|
{
|
|
auto parameterInfo = ctor->GetParameter(j);
|
|
if (parameterInfo->GetName() == ctorArgumentName)
|
|
{
|
|
if (baseTd->GetPropertyByName(propertyName, false))
|
|
{
|
|
resolvedTypeInfo.typeInfo = CopyTypeInfo(ctor->GetReturn());
|
|
resolvedTypeInfo.typeName = GlobalStringKey::Get(baseTd->GetTypeName());
|
|
return resolvedTypeInfo;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return resolvedTypeInfo;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_GetPropertyTypes
|
|
***********************************************************************/
|
|
|
|
bool Workflow_GetPropertyTypes(GuiResourcePrecompileContext& precompileContext, WString& errorPrefix, types::ResolvingResult& resolvingResult, IGuiInstanceLoader* loader, IGuiInstanceLoader::TypeInfo resolvedTypeInfo, GlobalStringKey prop, Ptr<GuiAttSetterRepr::SetterValue> setter, collections::List<types::PropertyResolving>& possibleInfos, GuiResourceError::List& errors)
|
|
{
|
|
resolvedTypeInfo = Workflow_AdjustPropertySearchType(precompileContext, resolvingResult, resolvedTypeInfo, prop);
|
|
bool reportedNotSupported = false;
|
|
IGuiInstanceLoader::PropertyInfo propertyInfo(resolvedTypeInfo, prop);
|
|
|
|
errorPrefix = L"Precompile: Property \"" + propertyInfo.propertyName.ToString() + L"\" of type \"" + resolvedTypeInfo.typeName.ToString() + L"\"";
|
|
{
|
|
auto currentLoader = loader;
|
|
|
|
while (currentLoader)
|
|
{
|
|
if (auto propertyTypeInfo = currentLoader->GetPropertyType(precompileContext, propertyInfo))
|
|
{
|
|
if (propertyTypeInfo->support == GuiInstancePropertyInfo::NotSupport)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition, errorPrefix + L" is not supported."));
|
|
reportedNotSupported = true;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
types::PropertyResolving resolving;
|
|
resolving.loader = currentLoader;
|
|
resolving.propertyInfo = propertyInfo;
|
|
resolving.info = propertyTypeInfo;
|
|
possibleInfos.Add(resolving);
|
|
|
|
if (setter->binding == GlobalStringKey::_Set)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (propertyTypeInfo->mergability == GuiInstancePropertyInfo::NotMerge)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
currentLoader = GetInstanceLoaderManager()->GetParentLoader(currentLoader);
|
|
}
|
|
}
|
|
|
|
if (possibleInfos.Count() == 0)
|
|
{
|
|
if (!reportedNotSupported)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition, errorPrefix + L" does not exist."));
|
|
}
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
WorkflowReferenceNamesVisitor
|
|
***********************************************************************/
|
|
|
|
class WorkflowReferenceNamesVisitor : public Object, public GuiValueRepr::IVisitor
|
|
{
|
|
public:
|
|
GuiResourcePrecompileContext& precompileContext;
|
|
types::ResolvingResult& resolvingResult;
|
|
vint& generatedNameCount;
|
|
GuiResourceError::List& errors;
|
|
|
|
List<types::PropertyResolving>& candidatePropertyTypeInfos;
|
|
IGuiInstanceLoader::TypeInfo resolvedTypeInfo;
|
|
vint selectedPropertyTypeInfo = -1;
|
|
|
|
WorkflowReferenceNamesVisitor(GuiResourcePrecompileContext& _precompileContext, types::ResolvingResult& _resolvingResult, List<types::PropertyResolving>& _candidatePropertyTypeInfos, vint& _generatedNameCount, GuiResourceError::List& _errors)
|
|
:precompileContext(_precompileContext)
|
|
, resolvingResult(_resolvingResult)
|
|
, candidatePropertyTypeInfos(_candidatePropertyTypeInfos)
|
|
, generatedNameCount(_generatedNameCount)
|
|
, errors(_errors)
|
|
{
|
|
}
|
|
|
|
void Visit(GuiTextRepr* repr)override
|
|
{
|
|
if (selectedPropertyTypeInfo == -1)
|
|
{
|
|
selectedPropertyTypeInfo = 0;
|
|
}
|
|
|
|
auto candidate = candidatePropertyTypeInfos[selectedPropertyTypeInfo];
|
|
auto propertyInfo = candidate.propertyInfo;
|
|
ITypeDescriptor* td = nullptr;
|
|
{
|
|
auto typeInfo = candidate.info->acceptableTypes[0];
|
|
if (auto deserializer = GetInstanceLoaderManager()->GetInstanceDeserializer(propertyInfo, typeInfo.Obj()))
|
|
{
|
|
td = deserializer->DeserializeAs(propertyInfo, typeInfo.Obj())->GetTypeDescriptor();
|
|
}
|
|
else
|
|
{
|
|
td = typeInfo->GetTypeDescriptor();
|
|
}
|
|
}
|
|
|
|
if (auto st = td->GetSerializableType())
|
|
{
|
|
Value value;
|
|
if (st->Deserialize(repr->text, value))
|
|
{
|
|
resolvingResult.propertyResolvings.Add(repr, candidate);
|
|
}
|
|
else
|
|
{
|
|
auto error
|
|
= L"Precompile: Property \""
|
|
+ propertyInfo.propertyName.ToString()
|
|
+ L"\" of type \""
|
|
+ propertyInfo.typeInfo.typeName.ToString()
|
|
+ L"\" does not accept a value of text \""
|
|
+ repr->text
|
|
+ L"\" because it is not in a correct format of the serializable type \""
|
|
+ td->GetTypeName()
|
|
+ L"\".";
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition, error));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (td->GetTypeDescriptorFlags())
|
|
{
|
|
case TypeDescriptorFlags::FlagEnum:
|
|
case TypeDescriptorFlags::NormalEnum:
|
|
case TypeDescriptorFlags::Struct:
|
|
{
|
|
if (auto expression = Workflow_ParseTextValue(precompileContext, td, { resolvingResult.resource }, repr->text, repr->tagPosition, errors))
|
|
{
|
|
resolvingResult.propertyResolvings.Add(repr, candidate);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
auto error
|
|
= L"Precompile: Property \""
|
|
+ propertyInfo.propertyName.ToString()
|
|
+ L"\" of type \""
|
|
+ propertyInfo.typeInfo.typeName.ToString()
|
|
+ L"\" does not accept a value of text \""
|
|
+ repr->text
|
|
+ L"\" because its type \""
|
|
+ td->GetTypeName()
|
|
+ L"\" is not serializable.";
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition, error));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Visit(GuiAttSetterRepr* repr)override
|
|
{
|
|
if (candidatePropertyTypeInfos.Count() > 0)
|
|
{
|
|
resolvingResult.propertyResolvings.Add(repr, candidatePropertyTypeInfos[selectedPropertyTypeInfo]);
|
|
}
|
|
|
|
bool isReferenceType = (resolvedTypeInfo.typeInfo->GetTypeDescriptor()->GetTypeDescriptorFlags() & TypeDescriptorFlags::ReferenceType) != TypeDescriptorFlags::Undefined;
|
|
if (repr->instanceName == GlobalStringKey::Empty)
|
|
{
|
|
if (isReferenceType)
|
|
{
|
|
auto name = GlobalStringKey::Get(L"<precompile>" + itow(generatedNameCount++));
|
|
repr->instanceName = name;
|
|
resolvingResult.typeInfos.Add(name, resolvedTypeInfo);
|
|
}
|
|
}
|
|
else if (resolvingResult.typeInfos.Keys().Contains(repr->instanceName))
|
|
{
|
|
auto error
|
|
= L"Precompile: Referece name \""
|
|
+ repr->instanceName.ToString()
|
|
+ L"\" conflict with an existing named object.";
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition, error));
|
|
}
|
|
else if (!isReferenceType)
|
|
{
|
|
auto error
|
|
= L"Precompile: Reference name \""
|
|
+ repr->instanceName.ToString()
|
|
+ L"\" cannot be added to a non-reference instance of type \""
|
|
+ resolvedTypeInfo.typeName.ToString()
|
|
+ L"\".";
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition, error));
|
|
}
|
|
else
|
|
{
|
|
resolvingResult.referenceNames.Add(repr->instanceName);
|
|
resolvingResult.typeInfos.Add(repr->instanceName, resolvedTypeInfo);
|
|
}
|
|
|
|
auto loader = GetInstanceLoaderManager()->GetLoader(resolvedTypeInfo.typeName);
|
|
|
|
for (auto [setter, index] : indexed(repr->setters.Values()))
|
|
{
|
|
List<types::PropertyResolving> possibleInfos;
|
|
auto prop = repr->setters.Keys()[index];
|
|
|
|
WString errorPrefix;
|
|
if (Workflow_GetPropertyTypes(precompileContext, errorPrefix, resolvingResult, loader, resolvedTypeInfo, prop, setter, possibleInfos, errors))
|
|
{
|
|
if (setter->binding == GlobalStringKey::Empty)
|
|
{
|
|
for (auto value : setter->values)
|
|
{
|
|
WorkflowReferenceNamesVisitor visitor(precompileContext, resolvingResult, possibleInfos, generatedNameCount, errors);
|
|
value->Accept(&visitor);
|
|
}
|
|
}
|
|
else if (setter->binding == GlobalStringKey::_Set)
|
|
{
|
|
if (possibleInfos[0].info->support == GuiInstancePropertyInfo::SupportSet)
|
|
{
|
|
auto setTarget = dynamic_cast<GuiAttSetterRepr*>(setter->values[0].Obj());
|
|
|
|
WorkflowReferenceNamesVisitor visitor(precompileContext, resolvingResult, possibleInfos, generatedNameCount, errors);
|
|
auto typeInfo = possibleInfos[0].info->acceptableTypes[0];
|
|
visitor.selectedPropertyTypeInfo = 0;
|
|
visitor.resolvedTypeInfo.typeName = GlobalStringKey::Get(typeInfo->GetTypeDescriptor()->GetTypeName());
|
|
visitor.resolvedTypeInfo.typeInfo = typeInfo;
|
|
setTarget->Accept(&visitor);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition, L"[INTERNAL-ERROR] " + errorPrefix + L" does not support the \"-set\" binding."));
|
|
}
|
|
}
|
|
else if (setter->binding != GlobalStringKey::Empty)
|
|
{
|
|
auto binder = GetInstanceLoaderManager()->GetInstanceBinder(setter->binding);
|
|
if (binder)
|
|
{
|
|
if (possibleInfos[0].info->usage == GuiInstancePropertyInfo::ConstructorArgument)
|
|
{
|
|
if (possibleInfos[0].info->bindability == GuiInstancePropertyInfo::NotBindable)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition,
|
|
errorPrefix +
|
|
L" cannot be assigned using binding \"-" +
|
|
setter->binding.ToString() +
|
|
L"\". Because it is a non-bindable constructor argument."));
|
|
}
|
|
else if (!binder->ApplicableToConstructorArgument())
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition,
|
|
errorPrefix +
|
|
L" cannot be assigned using binding \"-" +
|
|
setter->binding.ToString() +
|
|
L"\". Because it is a constructor argument, and this binding does not apply to any constructor argument."));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition,
|
|
errorPrefix +
|
|
L" cannot be assigned using an unexisting binding \"-" +
|
|
setter->binding.ToString() +
|
|
L"\"."));
|
|
}
|
|
|
|
if (setter->values.Count() == 1 && setter->values[0].Cast<GuiTextRepr>())
|
|
{
|
|
resolvingResult.propertyResolvings.Add(setter->values[0].Obj(), possibleInfos[0]);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition,
|
|
L"Precompile: Binder \"" +
|
|
setter->binding.ToString() +
|
|
L"\" requires the text value of property \"" +
|
|
prop.ToString() +
|
|
L"\"."));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Group<GlobalStringKey, IGuiInstanceLoader*> properties;
|
|
CopyFrom(
|
|
properties,
|
|
From(repr->setters)
|
|
.SelectMany([=](Pair<GlobalStringKey, Ptr<GuiAttSetterRepr::SetterValue>> item)
|
|
{
|
|
return From(item.value->values)
|
|
.Where([=](Ptr<GuiValueRepr> value)
|
|
{
|
|
return resolvingResult.propertyResolvings.Keys().Contains(value.Obj());
|
|
})
|
|
.Select([=](Ptr<GuiValueRepr> value)
|
|
{
|
|
auto loader = resolvingResult.propertyResolvings[value.Obj()].loader;
|
|
return Pair<GlobalStringKey, IGuiInstanceLoader*>(item.key, loader);
|
|
});
|
|
})
|
|
.Distinct()
|
|
);
|
|
|
|
if (resolvingResult.context->instance.Obj() != repr)
|
|
{
|
|
List<GlobalStringKey> requiredProps;
|
|
{
|
|
auto currentLoader = loader;
|
|
while (currentLoader)
|
|
{
|
|
currentLoader->GetRequiredPropertyNames(precompileContext, resolvedTypeInfo, requiredProps);
|
|
currentLoader = GetInstanceLoaderManager()->GetParentLoader(currentLoader);
|
|
}
|
|
}
|
|
for (auto prop : From(requiredProps).Distinct())
|
|
{
|
|
if (!properties.Keys().Contains(prop))
|
|
{
|
|
Ptr<GuiInstancePropertyInfo> info;
|
|
{
|
|
auto currentLoader = loader;
|
|
while (currentLoader && !info)
|
|
{
|
|
info = currentLoader->GetPropertyType(precompileContext, { resolvedTypeInfo, prop });
|
|
currentLoader = GetInstanceLoaderManager()->GetParentLoader(currentLoader);
|
|
}
|
|
}
|
|
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"Precompile: Missing required " +
|
|
WString(info->usage == GuiInstancePropertyInfo::ConstructorArgument ? L"constructor argument" : L"property") +
|
|
L" \"" +
|
|
prop.ToString() +
|
|
L"\" of type \"" +
|
|
resolvedTypeInfo.typeName.ToString() +
|
|
L"\"."));
|
|
}
|
|
}
|
|
}
|
|
|
|
while (properties.Count() > 0)
|
|
{
|
|
auto prop = properties.Keys()[0];
|
|
auto loader = properties.GetByIndex(0)[0];
|
|
IGuiInstanceLoader::PropertyInfo propertyInfo(resolvedTypeInfo, prop);
|
|
|
|
List<GlobalStringKey> pairProps;
|
|
loader->GetPairedProperties(precompileContext, propertyInfo, pairProps);
|
|
if (pairProps.Count() > 0)
|
|
{
|
|
List<GlobalStringKey> missingProps;
|
|
for (auto key : pairProps)
|
|
{
|
|
if (!properties.Contains(key, loader))
|
|
{
|
|
missingProps.Add(key);
|
|
}
|
|
}
|
|
|
|
if (missingProps.Count() > 0)
|
|
{
|
|
WString error
|
|
= L"Precompile: When you assign to property \""
|
|
+ prop.ToString()
|
|
+ L"\" of type \""
|
|
+ resolvedTypeInfo.typeName.ToString()
|
|
+ L"\", the following missing properties are required: ";
|
|
for (auto [key, index] : indexed(missingProps))
|
|
{
|
|
if (index > 0)error += L", ";
|
|
error += L"\"" + key.ToString() + L"\"";
|
|
}
|
|
error += L".";
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->setters[prop]->attPosition, error));
|
|
}
|
|
|
|
for (auto key : pairProps)
|
|
{
|
|
properties.Remove(key, loader);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
properties.Remove(prop, loader);
|
|
}
|
|
}
|
|
|
|
for (auto handler : repr->eventHandlers.Values())
|
|
{
|
|
if (handler->binding != GlobalStringKey::Empty)
|
|
{
|
|
auto binder = GetInstanceLoaderManager()->GetInstanceEventBinder(handler->binding);
|
|
if (!binder)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, handler->attPosition,
|
|
L"The appropriate IGuiInstanceEventBinder of binding \"-" +
|
|
handler->binding.ToString() +
|
|
L"\" cannot be found."));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Visit(GuiConstructorRepr* repr)override
|
|
{
|
|
bool found = false;
|
|
|
|
bool inferType = repr->typeNamespace == GlobalStringKey::Empty && repr->typeName == GlobalStringKey::_InferType;
|
|
if (inferType)
|
|
{
|
|
if (candidatePropertyTypeInfos.Count() == 1)
|
|
{
|
|
auto info = candidatePropertyTypeInfos[0].info;
|
|
if (info->acceptableTypes.Count() == 1)
|
|
{
|
|
auto typeInfo = info->acceptableTypes[0];
|
|
resolvedTypeInfo.typeName = GlobalStringKey::Get(typeInfo->GetTypeDescriptor()->GetTypeName());
|
|
resolvedTypeInfo.typeInfo = typeInfo;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (repr == resolvingResult.context->instance.Obj())
|
|
{
|
|
auto fullName = GlobalStringKey::Get(resolvingResult.context->className);
|
|
if (auto typeInfo = GetInstanceLoaderManager()->GetTypeInfoForType(fullName))
|
|
{
|
|
resolvedTypeInfo.typeName = fullName;
|
|
resolvedTypeInfo.typeInfo = typeInfo;
|
|
found = true;
|
|
}
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
auto source = FindInstanceLoadingSource(resolvingResult.context, repr);
|
|
resolvedTypeInfo.typeName = source.typeName;
|
|
resolvedTypeInfo.typeInfo = GetInstanceLoaderManager()->GetTypeInfoForType(source.typeName);
|
|
}
|
|
}
|
|
|
|
if (resolvingResult.context->instance == repr)
|
|
{
|
|
static const wchar_t Prefix[] = L"<ctor-parameter>";
|
|
static const vint PrefixLength = (vint)sizeof(Prefix) / sizeof(*Prefix) - 1;
|
|
|
|
auto source = FindInstanceLoadingSource(resolvingResult.context, repr);
|
|
if (auto baseTd = description::GetTypeDescriptor(source.typeName.ToString()))
|
|
{
|
|
if (auto ctorGroup = baseTd->GetConstructorGroup())
|
|
{
|
|
if (ctorGroup->GetMethodCount() == 1)
|
|
{
|
|
auto ctor = ctorGroup->GetMethod(0);
|
|
vint paramCount = ctor->GetParameterCount();
|
|
for (vint i = 0; i < paramCount; i++)
|
|
{
|
|
auto parameterInfo = ctor->GetParameter(i);
|
|
auto ctorArg = parameterInfo->GetName();
|
|
if (ctorArg.Length() > PrefixLength && ctorArg.Left(PrefixLength) == Prefix)
|
|
{
|
|
auto propName = ctorArg.Right(ctorArg.Length() - PrefixLength);
|
|
if (baseTd->GetPropertyByName(propName, false))
|
|
{
|
|
if (!repr->setters.Keys().Contains(GlobalStringKey::Get(propName)))
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"Precompile: Missing required property \"" +
|
|
propName +
|
|
L"\" of type \"" +
|
|
resolvedTypeInfo.typeName.ToString() +
|
|
L"\" for its base type \"" +
|
|
baseTd->GetTypeName() +
|
|
L"\"."));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (resolvedTypeInfo.typeInfo)
|
|
{
|
|
for (vint i = 0; i < candidatePropertyTypeInfos.Count(); i++)
|
|
{
|
|
const auto& typeInfos = candidatePropertyTypeInfos[i].info->acceptableTypes;
|
|
for (vint j = 0; j < typeInfos.Count(); j++)
|
|
{
|
|
if (resolvedTypeInfo.typeInfo->GetTypeDescriptor()->CanConvertTo(typeInfos[j]->GetTypeDescriptor()))
|
|
{
|
|
selectedPropertyTypeInfo = i;
|
|
goto FINISH_MATCHING;
|
|
}
|
|
}
|
|
}
|
|
FINISH_MATCHING:
|
|
|
|
if (selectedPropertyTypeInfo == -1 && candidatePropertyTypeInfos.Count() > 0)
|
|
{
|
|
auto propertyInfo = candidatePropertyTypeInfos[0].propertyInfo;
|
|
auto error
|
|
= L"Precompile: Property \""
|
|
+ propertyInfo.propertyName.ToString()
|
|
+ L"\" of type \""
|
|
+ propertyInfo.typeInfo.typeName.ToString()
|
|
+ L"\" does not accept a value of type \""
|
|
+ resolvedTypeInfo.typeName.ToString()
|
|
+ L"\" because it only accepts value of the following types: ";
|
|
|
|
for (vint i = 0; i < candidatePropertyTypeInfos.Count(); i++)
|
|
{
|
|
const auto& typeInfos = candidatePropertyTypeInfos[i].info->acceptableTypes;
|
|
for (vint j = 0; j < typeInfos.Count(); j++)
|
|
{
|
|
if (i != 0 || j != 0)
|
|
{
|
|
error += L", ";
|
|
}
|
|
error += L"\"" + typeInfos[j]->GetTypeFriendlyName() + L"\"";
|
|
}
|
|
}
|
|
|
|
error += L".";
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition, error));
|
|
}
|
|
else
|
|
{
|
|
if (repr->setters.Count() == 1 && repr->setters.Keys()[0] == GlobalStringKey::Empty)
|
|
{
|
|
auto setter = repr->setters.Values()[0];
|
|
if (setter->values.Count() == 1)
|
|
{
|
|
if (auto text = setter->values[0].Cast<GuiTextRepr>())
|
|
{
|
|
if (candidatePropertyTypeInfos.Count() == 0)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"Precompile: Type \"" +
|
|
resolvedTypeInfo.typeName.ToString() +
|
|
L"\" cannot be used to create an instance."));
|
|
}
|
|
else
|
|
{
|
|
Visit(text.Obj());
|
|
auto index = resolvingResult.propertyResolvings.Keys().IndexOf(text.Obj());
|
|
if (index != -1)
|
|
{
|
|
auto value = resolvingResult.propertyResolvings.Values()[index];
|
|
resolvingResult.propertyResolvings.Remove(text.Obj());
|
|
resolvingResult.propertyResolvings.Add(repr, value);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (resolvingResult.context->instance.Obj() != repr)
|
|
{
|
|
auto loader = GetInstanceLoaderManager()->GetLoader(resolvedTypeInfo.typeName);
|
|
while (loader)
|
|
{
|
|
if (loader->CanCreate(resolvedTypeInfo))
|
|
{
|
|
break;
|
|
}
|
|
loader = GetInstanceLoaderManager()->GetParentLoader(loader);
|
|
}
|
|
if (loader)
|
|
{
|
|
if (repr == resolvingResult.context->instance.Obj())
|
|
{
|
|
List<GlobalStringKey> propertyNames;
|
|
loader->GetPropertyNames(precompileContext, resolvedTypeInfo, propertyNames);
|
|
for (vint i = propertyNames.Count() - 1; i >= 0; i--)
|
|
{
|
|
auto info = loader->GetPropertyType(precompileContext, { resolvedTypeInfo, propertyNames[i] });
|
|
if (!info || info->usage == GuiInstancePropertyInfo::Property)
|
|
{
|
|
propertyNames.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
if (propertyNames.Count() == 1)
|
|
{
|
|
if (propertyNames[0] != GlobalStringKey::_ControlTemplate)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"Precompile: Type \"" +
|
|
resolvedTypeInfo.typeName.ToString() +
|
|
L"\" cannot be used to create a root instance, because its only constructor parameter is not for a the control template."));
|
|
}
|
|
}
|
|
else if (propertyNames.Count() > 1)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"Precompile: Type \"" +
|
|
resolvedTypeInfo.typeName.ToString() +
|
|
L"\" cannot be used to create a root instance, because it has more than one constructor parameters. A root instance type can only have one constructor parameter, which is for the control template."));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"Precompile: Type \"" +
|
|
resolvedTypeInfo.typeName.ToString() +
|
|
L"\" cannot be used to create an instance."));
|
|
}
|
|
}
|
|
Visit((GuiAttSetterRepr*)repr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"[INTERNAL-ERROR] Precompile: Failed to find type \"" +
|
|
(repr->typeNamespace == GlobalStringKey::Empty
|
|
? repr->typeName.ToString()
|
|
: repr->typeNamespace.ToString() + L":" + repr->typeName.ToString()
|
|
) +
|
|
L"\"."));
|
|
}
|
|
}
|
|
};
|
|
|
|
Ptr<reflection::description::ITypeInfo> Workflow_GetSuggestedParameterType(GuiResourcePrecompileContext& precompileContext, reflection::description::ITypeDescriptor* typeDescriptor)
|
|
{
|
|
auto elementType = Ptr(new TypeDescriptorTypeInfo(typeDescriptor, TypeInfoHint::Normal));
|
|
if ((typeDescriptor->GetTypeDescriptorFlags() & TypeDescriptorFlags::ReferenceType) != TypeDescriptorFlags::Undefined)
|
|
{
|
|
bool isShared = false;
|
|
bool isRaw = false;
|
|
if (auto ctorGroup = typeDescriptor->GetConstructorGroup())
|
|
{
|
|
vint count = ctorGroup->GetMethodCount();
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto returnType = ctorGroup->GetMethod(i)->GetReturn();
|
|
switch (returnType->GetDecorator())
|
|
{
|
|
case ITypeInfo::RawPtr: isRaw = true; break;
|
|
case ITypeInfo::SharedPtr: isShared = true; break;
|
|
default:;
|
|
}
|
|
}
|
|
}
|
|
if (!isShared && !isRaw)
|
|
{
|
|
return Ptr(new SharedPtrTypeInfo(elementType));
|
|
}
|
|
else if (isShared)
|
|
{
|
|
return Ptr(new SharedPtrTypeInfo(elementType));
|
|
}
|
|
else
|
|
{
|
|
return Ptr(new RawPtrTypeInfo(elementType));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return elementType;
|
|
}
|
|
}
|
|
|
|
IGuiInstanceLoader::TypeInfo Workflow_CollectReferences(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GuiResourceError::List& errors)
|
|
{
|
|
for (auto parameter : resolvingResult.context->parameters)
|
|
{
|
|
auto type = GetTypeDescriptor(parameter->className.ToString());
|
|
if (!type)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, parameter->classPosition,
|
|
L"Precompile: Cannot find type \"" +
|
|
parameter->className.ToString() +
|
|
L"\"."));
|
|
}
|
|
else if (resolvingResult.typeInfos.Keys().Contains(parameter->name))
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, parameter->classPosition,
|
|
L"[INTERNAL-ERROR] Precompile: Parameter \"" +
|
|
parameter->name.ToString() +
|
|
L"\" conflict with an existing named object."));
|
|
}
|
|
else
|
|
{
|
|
auto referenceType = Workflow_GetSuggestedParameterType(precompileContext, type);
|
|
resolvingResult.typeInfos.Add(parameter->name, { GlobalStringKey::Get(type->GetTypeName()),referenceType });
|
|
}
|
|
}
|
|
|
|
List<types::PropertyResolving> infos;
|
|
vint generatedNameCount = 0;
|
|
WorkflowReferenceNamesVisitor visitor(precompileContext, resolvingResult, infos, generatedNameCount, errors);
|
|
resolvingResult.context->instance->Accept(&visitor);
|
|
return visitor.resolvedTypeInfo;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\WORKFLOWCODEGEN\GUIINSTANCELOADER_WORKFLOWGENERATEBINDINGS.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace workflow;
|
|
using namespace collections;
|
|
using namespace reflection::description;
|
|
|
|
/***********************************************************************
|
|
WorkflowGenerateBindingVisitor
|
|
***********************************************************************/
|
|
|
|
class WorkflowGenerateBindingVisitor : public Object, public GuiValueRepr::IVisitor
|
|
{
|
|
public:
|
|
GuiResourcePrecompileContext& precompileContext;
|
|
types::ResolvingResult& resolvingResult;
|
|
Ptr<WfBlockStatement> statements;
|
|
GuiResourceError::List& errors;
|
|
|
|
WorkflowGenerateBindingVisitor(GuiResourcePrecompileContext& _precompileContext, types::ResolvingResult& _resolvingResult, Ptr<WfBlockStatement> _statements, GuiResourceError::List& _errors)
|
|
:precompileContext(_precompileContext)
|
|
, resolvingResult(_resolvingResult)
|
|
, errors(_errors)
|
|
, statements(_statements)
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Ptr<WfStatement> ProcessPropertyBinding(
|
|
GuiAttSetterRepr* repr,
|
|
IGuiInstanceLoader::TypeInfo reprTypeInfo,
|
|
Ptr<GuiAttSetterRepr::SetterValue> setter,
|
|
GlobalStringKey propertyName
|
|
)
|
|
{
|
|
if (auto binder = GetInstanceLoaderManager()->GetInstanceBinder(setter->binding))
|
|
{
|
|
auto propertyResolving = resolvingResult.propertyResolvings[setter->values[0].Obj()];
|
|
if (propertyResolving.info->usage == GuiInstancePropertyInfo::Property)
|
|
{
|
|
WString expressionCode = setter->values[0].Cast<GuiTextRepr>()->text;
|
|
auto instancePropertyInfo = reprTypeInfo.typeInfo->GetTypeDescriptor()->GetPropertyByName(propertyName.ToString(), true);
|
|
|
|
if (instancePropertyInfo || !binder->RequirePropertyExist())
|
|
{
|
|
if (auto statement = binder->GenerateInstallStatement(
|
|
precompileContext,
|
|
resolvingResult,
|
|
repr->instanceName,
|
|
instancePropertyInfo,
|
|
propertyResolving.loader,
|
|
propertyResolving.propertyInfo,
|
|
propertyResolving.info,
|
|
expressionCode,
|
|
setter->values[0]->tagPosition,
|
|
errors))
|
|
{
|
|
return statement;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition,
|
|
L"Precompile: Binder \"" +
|
|
setter->binding.ToString() +
|
|
L"\" requires property \"" +
|
|
propertyName.ToString() +
|
|
L"\" to physically appear in type \"" +
|
|
reprTypeInfo.typeName.ToString() +
|
|
L"\"."));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition,
|
|
L"[INTERNAL-ERROR] Precompile: The appropriate IGuiInstanceBinder of binding \"-" +
|
|
setter->binding.ToString() +
|
|
L"\" cannot be found."));
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Ptr<WfStatement> ProcessEventBinding(
|
|
GuiAttSetterRepr* repr,
|
|
IGuiInstanceLoader::TypeInfo reprTypeInfo,
|
|
Ptr<GuiAttSetterRepr::EventValue> handler,
|
|
GlobalStringKey propertyName
|
|
)
|
|
{
|
|
auto td = reprTypeInfo.typeInfo->GetTypeDescriptor();
|
|
auto eventInfo = td->GetEventByName(propertyName.ToString(), true);
|
|
|
|
if (!eventInfo)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, handler->attPosition,
|
|
L"[INTERNAL-ERROR] Precompile: Event \"" +
|
|
propertyName.ToString() +
|
|
L"\" cannot be found in type \"" +
|
|
reprTypeInfo.typeName.ToString() +
|
|
L"\"."));
|
|
}
|
|
else
|
|
{
|
|
if (handler->binding == GlobalStringKey::Empty)
|
|
{
|
|
return Workflow_InstallEvent(precompileContext, resolvingResult, repr->instanceName, eventInfo, handler->value);
|
|
}
|
|
else
|
|
{
|
|
auto binder = GetInstanceLoaderManager()->GetInstanceEventBinder(handler->binding);
|
|
if (binder)
|
|
{
|
|
return binder->GenerateInstallStatement(precompileContext, resolvingResult, repr->instanceName, eventInfo, handler->value, handler->valuePosition, errors);
|
|
}
|
|
else
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, handler->attPosition,
|
|
L"[INTERNAL-ERROR] The appropriate IGuiInstanceEventBinder of binding \"-" +
|
|
handler->binding.ToString() +
|
|
L"\" cannot be found."));
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Visit(GuiTextRepr* repr)override
|
|
{
|
|
}
|
|
|
|
void Visit(GuiAttSetterRepr* repr)override
|
|
{
|
|
IGuiInstanceLoader::TypeInfo reprTypeInfo;
|
|
if (repr->instanceName != GlobalStringKey::Empty)
|
|
{
|
|
reprTypeInfo = resolvingResult.typeInfos[repr->instanceName];
|
|
}
|
|
|
|
if (reprTypeInfo.typeInfo && (reprTypeInfo.typeInfo->GetTypeDescriptor()->GetTypeDescriptorFlags() & TypeDescriptorFlags::ReferenceType) != TypeDescriptorFlags::Undefined)
|
|
{
|
|
WORKFLOW_ENVIRONMENT_VARIABLE_ADD
|
|
|
|
for (auto [setter, index] : indexed(repr->setters.Values()))
|
|
{
|
|
auto propertyName = repr->setters.Keys()[index];
|
|
if (setter->binding != GlobalStringKey::Empty && setter->binding != GlobalStringKey::_Set)
|
|
{
|
|
if (auto statement = ProcessPropertyBinding(repr, reprTypeInfo, setter, propertyName))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, setter->values[0]->tagPosition, statement);
|
|
statements->statements.Add(statement);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (auto value : setter->values)
|
|
{
|
|
value->Accept(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (auto [handler, index] : indexed(repr->eventHandlers.Values()))
|
|
{
|
|
if (reprTypeInfo.typeInfo)
|
|
{
|
|
GlobalStringKey propertyName = repr->eventHandlers.Keys()[index];
|
|
if (auto statement = ProcessEventBinding(repr, reprTypeInfo, handler, propertyName))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, handler->valuePosition, statement);
|
|
statements->statements.Add(statement);
|
|
}
|
|
}
|
|
}
|
|
|
|
WORKFLOW_ENVIRONMENT_VARIABLE_REMOVE
|
|
}
|
|
}
|
|
|
|
void Visit(GuiConstructorRepr* repr)override
|
|
{
|
|
Visit((GuiAttSetterRepr*)repr);
|
|
}
|
|
};
|
|
|
|
void Workflow_GenerateBindings(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, Ptr<WfBlockStatement> statements, GuiResourceError::List& errors)
|
|
{
|
|
WorkflowGenerateBindingVisitor visitor(precompileContext, resolvingResult, statements, errors);
|
|
resolvingResult.context->instance->Accept(&visitor);
|
|
|
|
for (auto localized : resolvingResult.context->localizeds)
|
|
{
|
|
auto code = L"bind(" + localized->className.ToString() + L"::Get(presentation::controls::GuiApplication::GetApplication().Locale))";
|
|
if (auto bindExpr = Workflow_ParseExpression(precompileContext, { resolvingResult.resource }, code, localized->tagPosition, errors))
|
|
{
|
|
auto instancePropertyInfo = resolvingResult.rootTypeInfo.typeInfo->GetTypeDescriptor()->GetPropertyByName(localized->name.ToString(), true);
|
|
if (auto statement = Workflow_InstallBindProperty(precompileContext, resolvingResult, resolvingResult.context->instance->instanceName, instancePropertyInfo, bindExpr))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, localized->tagPosition, statement);
|
|
statements->statements.Add(statement);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\WORKFLOWCODEGEN\GUIINSTANCELOADER_WORKFLOWGENERATECREATING.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace collections;
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
using namespace reflection::description;
|
|
|
|
/***********************************************************************
|
|
WorkflowGenerateCreatingVisitor
|
|
***********************************************************************/
|
|
|
|
class WorkflowGenerateCreatingVisitor : public Object, public GuiValueRepr::IVisitor
|
|
{
|
|
public:
|
|
GuiResourcePrecompileContext& precompileContext;
|
|
types::ResolvingResult& resolvingResult;
|
|
Ptr<WfBlockStatement> statements;
|
|
GuiResourceError::List& errors;
|
|
|
|
WorkflowGenerateCreatingVisitor(GuiResourcePrecompileContext& _precompileContext, types::ResolvingResult& _resolvingResult, Ptr<WfBlockStatement> _statements, GuiResourceError::List& _errors)
|
|
:precompileContext(_precompileContext)
|
|
, resolvingResult(_resolvingResult)
|
|
, errors(_errors)
|
|
, statements(_statements)
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
IGuiInstanceLoader::ArgumentInfo GetArgumentInfo(GuiResourceTextPos attPosition, GuiValueRepr* repr)
|
|
{
|
|
IGuiInstanceLoader::PropertyInfo propertyInfo;
|
|
Ptr<ITypeInfo> typeInfo = nullptr;
|
|
bool serializable = false;
|
|
WString textValue;
|
|
GuiResourceTextPos textValuePosition;
|
|
GuiConstructorRepr* ctor = nullptr;
|
|
|
|
if (auto text = dynamic_cast<GuiTextRepr*>(repr))
|
|
{
|
|
auto resolving = resolvingResult.propertyResolvings[repr];
|
|
propertyInfo = resolving.propertyInfo;
|
|
typeInfo = resolving.info->acceptableTypes[0];
|
|
|
|
serializable = true;
|
|
textValue = text->text;
|
|
textValuePosition = text->tagPosition;
|
|
}
|
|
else if ((ctor = dynamic_cast<GuiConstructorRepr*>(repr)))
|
|
{
|
|
if (ctor->instanceName == GlobalStringKey::Empty)
|
|
{
|
|
auto resolving = resolvingResult.propertyResolvings[repr];
|
|
propertyInfo = resolving.propertyInfo;
|
|
typeInfo = resolving.info->acceptableTypes[0];
|
|
}
|
|
else
|
|
{
|
|
typeInfo = resolvingResult.typeInfos[ctor->instanceName].typeInfo;
|
|
}
|
|
|
|
if ((typeInfo->GetTypeDescriptor()->GetTypeDescriptorFlags() & TypeDescriptorFlags::StructType) != TypeDescriptorFlags::Undefined)
|
|
{
|
|
serializable = true;
|
|
auto value = ctor->setters.Values()[0]->values[0].Cast<GuiTextRepr>();
|
|
textValue = value->text;
|
|
textValuePosition = value->tagPosition;
|
|
}
|
|
}
|
|
|
|
IGuiInstanceLoader::ArgumentInfo argumentInfo;
|
|
argumentInfo.typeInfo = typeInfo;
|
|
argumentInfo.attPosition = attPosition;
|
|
|
|
if (serializable)
|
|
{
|
|
if (auto deserializer = GetInstanceLoaderManager()->GetInstanceDeserializer(propertyInfo, typeInfo.Obj()))
|
|
{
|
|
auto typeInfoAs = deserializer->DeserializeAs(propertyInfo, typeInfo.Obj());
|
|
if (auto expression = Workflow_ParseTextValue(precompileContext, typeInfoAs->GetTypeDescriptor(), { resolvingResult.resource }, textValue, textValuePosition, errors))
|
|
{
|
|
argumentInfo.expression = deserializer->Deserialize(precompileContext, resolvingResult, propertyInfo, typeInfo.Obj(), expression, textValuePosition, errors);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
argumentInfo.expression = Workflow_ParseTextValue(precompileContext, typeInfo->GetTypeDescriptor(), { resolvingResult.resource }, textValue, textValuePosition, errors);
|
|
}
|
|
argumentInfo.valuePosition = textValuePosition;
|
|
}
|
|
else
|
|
{
|
|
repr->Accept(this);
|
|
|
|
auto ref = Ptr(new WfReferenceExpression);
|
|
ref->name.value = ctor->instanceName.ToString();
|
|
argumentInfo.expression = ref;
|
|
}
|
|
|
|
if (argumentInfo.expression)
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, repr->tagPosition, argumentInfo.expression);
|
|
}
|
|
return argumentInfo;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Ptr<WfStatement> ProcessPropertySet(
|
|
IGuiInstanceLoader::PropertyInfo propInfo,
|
|
GuiAttSetterRepr* repr,
|
|
Ptr<GuiAttSetterRepr::SetterValue> setter,
|
|
GuiAttSetterRepr* setTarget
|
|
)
|
|
{
|
|
auto info = resolvingResult.propertyResolvings[setTarget];
|
|
vint errorCount = errors.Count();
|
|
if (auto expr = info.loader->GetParameter(precompileContext, resolvingResult, propInfo, repr->instanceName, setter->attPosition, errors))
|
|
{
|
|
auto refInstance = Ptr(new WfReferenceExpression);
|
|
refInstance->name.value = setTarget->instanceName.ToString();
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refInstance;
|
|
assign->second = expr;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
|
|
return stat;
|
|
}
|
|
else if (errorCount == errors.Count())
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setTarget->tagPosition,
|
|
L"[INTERNAL-ERROR] Precompile: Something is wrong when retriving the property \"" +
|
|
propInfo.propertyName.ToString() +
|
|
L"\" from an instance of type \"" +
|
|
propInfo.typeInfo.typeName.ToString() +
|
|
L"\"."));
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Ptr<WfStatement> ProcessPropertyCollection(
|
|
IGuiInstanceLoader::PropertyInfo propInfo,
|
|
GuiAttSetterRepr* repr,
|
|
Group<GlobalStringKey, IGuiInstanceLoader*>& usedProps,
|
|
Ptr<GuiAttSetterRepr::SetterValue> setter,
|
|
types::PropertyResolving info,
|
|
Ptr<GuiValueRepr> value
|
|
)
|
|
{
|
|
if (!usedProps.Contains(propInfo.propertyName, info.loader))
|
|
{
|
|
usedProps.Add(propInfo.propertyName, info.loader);
|
|
}
|
|
|
|
vint errorCount = errors.Count();
|
|
IGuiInstanceLoader::ArgumentMap arguments;
|
|
arguments.Add(propInfo.propertyName, GetArgumentInfo(setter->attPosition, value.Obj()));
|
|
if (auto stat = info.loader->AssignParameters(precompileContext, resolvingResult, propInfo.typeInfo, repr->instanceName, arguments, setter->attPosition, errors))
|
|
{
|
|
return stat;
|
|
}
|
|
else if (errorCount == errors.Count())
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, value->tagPosition,
|
|
L"[INTERNAL-ERROR] Precompile: Something is wrong when assigning to property " +
|
|
propInfo.propertyName.ToString() +
|
|
L" to an instance of type \"" +
|
|
propInfo.typeInfo.typeName.ToString() +
|
|
L"\"."));
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Ptr<WfStatement> ProcessPropertyOthers(
|
|
IGuiInstanceLoader::PropertyInfo propInfo,
|
|
GuiAttSetterRepr* repr,
|
|
Group<GlobalStringKey, IGuiInstanceLoader*>& usedProps,
|
|
Ptr<GuiAttSetterRepr::SetterValue> setter,
|
|
types::PropertyResolving info,
|
|
Ptr<GuiValueRepr> value
|
|
)
|
|
{
|
|
List<GlobalStringKey> pairedProps;
|
|
info.loader->GetPairedProperties(precompileContext, propInfo, pairedProps);
|
|
if (pairedProps.Count() == 0)
|
|
{
|
|
pairedProps.Add(propInfo.propertyName);
|
|
}
|
|
|
|
vint errorCount = errors.Count();
|
|
IGuiInstanceLoader::ArgumentMap arguments;
|
|
for (auto pairedProp : pairedProps)
|
|
{
|
|
usedProps.Add(pairedProp, info.loader);
|
|
auto pairedSetter = repr->setters[pairedProp];
|
|
for (auto pairedValue : pairedSetter->values)
|
|
{
|
|
auto pairedInfo = resolvingResult.propertyResolvings[pairedValue.Obj()];
|
|
if (pairedInfo.loader == info.loader)
|
|
{
|
|
arguments.Add(pairedProp, GetArgumentInfo(pairedSetter->attPosition, pairedValue.Obj()));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (auto stat = info.loader->AssignParameters(precompileContext, resolvingResult, propInfo.typeInfo, repr->instanceName, arguments, setter->attPosition, errors))
|
|
{
|
|
return stat;
|
|
}
|
|
else if (errorCount == errors.Count())
|
|
{
|
|
WString propNames;
|
|
for (auto [pairedProp, propIndex] : indexed(pairedProps))
|
|
{
|
|
if (propIndex > 0)propNames += L", ";
|
|
propNames += L"\"" + pairedProp.ToString() + L"\"";
|
|
}
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, value->tagPosition,
|
|
L"[INTERNAL-ERROR] Precompile: Something is wrong when assigning to properties " +
|
|
propNames +
|
|
L" to an instance of type \"" +
|
|
propInfo.typeInfo.typeName.ToString() +
|
|
L"\"."));
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Visit(GuiTextRepr* repr)override
|
|
{
|
|
}
|
|
|
|
void Visit(GuiAttSetterRepr* repr)override
|
|
{
|
|
auto reprTypeInfo = resolvingResult.typeInfos[repr->instanceName];
|
|
|
|
if (reprTypeInfo.typeInfo && (reprTypeInfo.typeInfo->GetTypeDescriptor()->GetTypeDescriptorFlags() & TypeDescriptorFlags::ReferenceType) != TypeDescriptorFlags::Undefined)
|
|
{
|
|
WORKFLOW_ENVIRONMENT_VARIABLE_ADD
|
|
|
|
Group<GlobalStringKey, IGuiInstanceLoader*> usedProps;
|
|
for (auto prop : From(repr->setters.Keys()).Reverse())
|
|
{
|
|
auto setter = repr->setters[prop];
|
|
IGuiInstanceLoader::PropertyInfo propInfo(reprTypeInfo, prop);
|
|
if (setter->binding == GlobalStringKey::_Set)
|
|
{
|
|
auto setTarget = dynamic_cast<GuiAttSetterRepr*>(setter->values[0].Obj());
|
|
if (auto statement = ProcessPropertySet(propInfo, repr, setter, setTarget))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, setTarget->tagPosition, statement);
|
|
statements->statements.Add(statement);
|
|
}
|
|
setTarget->Accept(this);
|
|
}
|
|
else if (setter->binding == GlobalStringKey::Empty)
|
|
{
|
|
for (auto value : setter->values)
|
|
{
|
|
auto info = resolvingResult.propertyResolvings[value.Obj()];
|
|
if (info.info->usage == GuiInstancePropertyInfo::Property)
|
|
{
|
|
if (info.info->support == GuiInstancePropertyInfo::SupportCollection)
|
|
{
|
|
if (auto statement = ProcessPropertyCollection(propInfo, repr, usedProps, setter, info, value))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, value->tagPosition, statement);
|
|
statements->statements.Add(statement);
|
|
}
|
|
}
|
|
else if (!usedProps.Contains(prop, info.loader))
|
|
{
|
|
if (auto statement = ProcessPropertyOthers(propInfo, repr, usedProps, setter, info, value))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, value->tagPosition, statement);
|
|
statements->statements.Add(statement);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
WORKFLOW_ENVIRONMENT_VARIABLE_REMOVE
|
|
}
|
|
}
|
|
|
|
void FillCtorArguments(GuiConstructorRepr* repr, IGuiInstanceLoader* loader, const IGuiInstanceLoader::TypeInfo& typeInfo, IGuiInstanceLoader::ArgumentMap& arguments)
|
|
{
|
|
WORKFLOW_ENVIRONMENT_VARIABLE_ADD
|
|
|
|
for (auto [prop, index] : indexed(repr->setters.Keys()))
|
|
{
|
|
auto setter = repr->setters.Values()[index];
|
|
auto propertyResolving = resolvingResult.propertyResolvings[setter->values[0].Obj()];
|
|
if (propertyResolving.info->usage != GuiInstancePropertyInfo::ConstructorArgument) continue;
|
|
|
|
if (setter->binding == GlobalStringKey::Empty)
|
|
{
|
|
for (auto value : setter->values)
|
|
{
|
|
auto argument = GetArgumentInfo(setter->attPosition, value.Obj());
|
|
if (argument.typeInfo && argument.expression)
|
|
{
|
|
arguments.Add(prop, argument);
|
|
}
|
|
}
|
|
}
|
|
else if (auto binder = GetInstanceLoaderManager()->GetInstanceBinder(setter->binding))
|
|
{
|
|
auto value = setter->values[0].Cast<GuiTextRepr>();
|
|
if (auto expression = binder->GenerateConstructorArgument(precompileContext, resolvingResult, loader, propertyResolving.propertyInfo, propertyResolving.info, value->text, value->tagPosition, errors))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, value->tagPosition, expression);
|
|
|
|
IGuiInstanceLoader::ArgumentInfo argument;
|
|
argument.expression = expression;
|
|
argument.typeInfo = propertyResolving.info->acceptableTypes[0];
|
|
argument.attPosition = setter->attPosition;
|
|
arguments.Add(prop, argument);
|
|
}
|
|
}
|
|
else if (setter->binding != GlobalStringKey::_Set)
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, setter->attPosition,
|
|
L"[INTERNAL-ERROR] Precompile: The appropriate IGuiInstanceBinder of binding \"-" +
|
|
setter->binding.ToString() +
|
|
L"\" cannot be found."));
|
|
}
|
|
}
|
|
|
|
WORKFLOW_ENVIRONMENT_VARIABLE_REMOVE
|
|
}
|
|
|
|
void Visit(GuiConstructorRepr* repr)override
|
|
{
|
|
IGuiInstanceLoader::TypeInfo ctorTypeInfo;
|
|
if (resolvingResult.context->instance.Obj() == repr)
|
|
{
|
|
auto source = FindInstanceLoadingSource(resolvingResult.context, repr);
|
|
ctorTypeInfo.typeName = source.typeName;
|
|
|
|
auto typeInfo = GetInstanceLoaderManager()->GetTypeInfoForType(source.typeName);
|
|
ctorTypeInfo.typeInfo = typeInfo;
|
|
}
|
|
else
|
|
{
|
|
ctorTypeInfo = resolvingResult.typeInfos[repr->instanceName];
|
|
}
|
|
|
|
auto ctorLoader = GetInstanceLoaderManager()->GetLoader(ctorTypeInfo.typeName);
|
|
while (ctorLoader)
|
|
{
|
|
if (ctorLoader->CanCreate(ctorTypeInfo))
|
|
{
|
|
break;
|
|
}
|
|
ctorLoader = GetInstanceLoaderManager()->GetParentLoader(ctorLoader);
|
|
}
|
|
|
|
if (resolvingResult.context->instance.Obj() == repr)
|
|
{
|
|
resolvingResult.rootLoader = ctorLoader;
|
|
FillCtorArguments(repr, ctorLoader, ctorTypeInfo, resolvingResult.rootCtorArguments);
|
|
|
|
{
|
|
auto refInstance = Ptr(new WfReferenceExpression);
|
|
refInstance->name.value = repr->instanceName.ToString();
|
|
|
|
auto refThis = Ptr(new WfReferenceExpression);
|
|
refThis->name.value = L"<this>";
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refInstance;
|
|
assign->second = refThis;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
|
|
statements->statements.Add(stat);
|
|
}
|
|
|
|
if (resolvingResult.rootCtorArguments.Count() > 0)
|
|
{
|
|
if (auto stat = ctorLoader->InitializeRootInstance(precompileContext, resolvingResult, ctorTypeInfo, repr->instanceName, resolvingResult.rootCtorArguments, errors))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, resolvingResult.context->tagPosition, stat);
|
|
statements->statements.Add(stat);
|
|
}
|
|
}
|
|
|
|
for (auto parameter : resolvingResult.context->parameters)
|
|
{
|
|
auto refInstance = Ptr(new WfReferenceExpression);
|
|
refInstance->name.value = parameter->name.ToString();
|
|
|
|
auto refThis = Ptr(new WfReferenceExpression);
|
|
refThis->name.value = L"<this>";
|
|
|
|
auto refParameter = Ptr(new WfMemberExpression);
|
|
refParameter->parent = refThis;
|
|
refParameter->name.value = parameter->name.ToString();
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = refInstance;
|
|
assign->second = refParameter;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
|
|
statements->statements.Add(stat);
|
|
Workflow_RecordScriptPosition(precompileContext, parameter->tagPosition, (Ptr<WfStatement>)stat);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IGuiInstanceLoader::ArgumentMap arguments;
|
|
FillCtorArguments(repr, ctorLoader, ctorTypeInfo, arguments);
|
|
|
|
vint errorCount = errors.Count();
|
|
if (auto ctorStats = ctorLoader->CreateInstance(precompileContext, resolvingResult, ctorTypeInfo, repr->instanceName, arguments, repr->tagPosition, errors))
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, resolvingResult.context->tagPosition, ctorStats);
|
|
statements->statements.Add(ctorStats);
|
|
}
|
|
else if (errorCount == errors.Count())
|
|
{
|
|
errors.Add(GuiResourceError({ resolvingResult.resource }, repr->tagPosition,
|
|
L"[INTERNAL-ERROR] Precompile: Something is wrong when creating an instance of type \"" +
|
|
ctorTypeInfo.typeName.ToString() +
|
|
L"\"."));
|
|
}
|
|
}
|
|
Visit((GuiAttSetterRepr*)repr);
|
|
}
|
|
};
|
|
|
|
void Workflow_GenerateCreating(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, Ptr<WfBlockStatement> statements, GuiResourceError::List& errors)
|
|
{
|
|
WorkflowGenerateCreatingVisitor visitor(precompileContext, resolvingResult, statements, errors);
|
|
resolvingResult.context->instance->Accept(&visitor);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
.\WORKFLOWCODEGEN\GUIINSTANCELOADER_WORKFLOWINSTALLBINDINGS.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
using namespace reflection::description;
|
|
using namespace collections;
|
|
|
|
using namespace controls;
|
|
using namespace compositions;
|
|
|
|
/***********************************************************************
|
|
Workflow_InstallBindProperty
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfExpression> Workflow_GetUriProperty(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& protocol, const WString& path, GuiResourceTextPos attPosition, GuiResourceError::List& errors)
|
|
{
|
|
Ptr<WfExpression> resourceExpr;
|
|
{
|
|
auto refResolver = Ptr(new WfReferenceExpression);
|
|
refResolver->name.value = L"<this>";
|
|
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = refResolver;
|
|
member->name.value = L"ResolveResource";
|
|
|
|
auto valueProtocol = Ptr(new WfStringExpression);
|
|
valueProtocol->value.value = protocol;
|
|
|
|
auto valuePath = Ptr(new WfStringExpression);
|
|
valuePath->value.value = path;
|
|
|
|
auto valueBool = Ptr(new WfLiteralExpression);
|
|
valueBool->value = WfLiteralValue::True;
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = member;
|
|
call->arguments.Add(valueProtocol);
|
|
call->arguments.Add(valuePath);
|
|
call->arguments.Add(valueBool);
|
|
|
|
resourceExpr = call;
|
|
}
|
|
|
|
auto td = propInfo->acceptableTypes[0]->GetTypeDescriptor();
|
|
Ptr<ITypeInfo> convertedType;
|
|
{
|
|
if (td->GetSerializableType())
|
|
{
|
|
convertedType = TypeInfoRetriver<Ptr<GuiTextData>>::CreateTypeInfo();
|
|
}
|
|
else if (td == description::GetTypeDescriptor<INativeImage>() || td == description::GetTypeDescriptor<GuiImageData>())
|
|
{
|
|
convertedType = TypeInfoRetriver<Ptr<GuiImageData>>::CreateTypeInfo();
|
|
}
|
|
else
|
|
{
|
|
auto elementType = Ptr(new TypeDescriptorTypeInfo(td, TypeInfoHint::Normal));
|
|
auto pointerType = Ptr(new SharedPtrTypeInfo(elementType));
|
|
convertedType = pointerType;
|
|
}
|
|
}
|
|
|
|
Ptr<WfExpression> convertedExpr;
|
|
{
|
|
auto cast = Ptr(new WfTypeCastingExpression);
|
|
cast->expression = resourceExpr;
|
|
cast->type = GetTypeFromTypeInfo(convertedType.Obj());
|
|
cast->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
convertedExpr = cast;
|
|
}
|
|
|
|
Ptr<WfExpression> evalExpr;
|
|
{
|
|
if (td->GetSerializableType())
|
|
{
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = convertedExpr;
|
|
member->name.value = L"Text";
|
|
|
|
auto elementType = Ptr(new TypeDescriptorTypeInfo(td, TypeInfoHint::Normal));
|
|
|
|
auto cast = Ptr(new WfTypeCastingExpression);
|
|
cast->expression = member;
|
|
cast->type = GetTypeFromTypeInfo(elementType.Obj());
|
|
cast->strategy = WfTypeCastingStrategy::Strong;
|
|
|
|
evalExpr = cast;
|
|
}
|
|
else if (td == description::GetTypeDescriptor<INativeImage>())
|
|
{
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = convertedExpr;
|
|
member->name.value = L"Image";
|
|
|
|
evalExpr = member;
|
|
}
|
|
else
|
|
{
|
|
evalExpr = convertedExpr;
|
|
}
|
|
}
|
|
|
|
return evalExpr;
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> Workflow_InstallUriProperty(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, const WString& protocol, const WString& path, GuiResourceTextPos attPosition, GuiResourceError::List& errors)
|
|
{
|
|
auto evalExpr = Workflow_GetUriProperty(precompileContext, resolvingResult, loader, prop, propInfo, protocol, path, attPosition, errors);
|
|
|
|
IGuiInstanceLoader::ArgumentMap arguments;
|
|
{
|
|
IGuiInstanceLoader::ArgumentInfo argumentInfo;
|
|
argumentInfo.typeInfo = propInfo->acceptableTypes[0];
|
|
argumentInfo.expression = evalExpr;
|
|
argumentInfo.attPosition = attPosition;
|
|
arguments.Add(prop.propertyName, argumentInfo);
|
|
}
|
|
|
|
return loader->AssignParameters(precompileContext, resolvingResult, prop.typeInfo, variableName, arguments, attPosition, errors);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_InstallBindProperty
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfStatement> Workflow_InstallBindProperty(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IPropertyInfo* propertyInfo, Ptr<workflow::WfExpression> bindExpression)
|
|
{
|
|
auto subBlock = Ptr(new WfBlockStatement);
|
|
{
|
|
auto var = Ptr(new WfVariableDeclaration);
|
|
var->name.value = L"<created-subscription>";
|
|
var->expression = bindExpression;
|
|
|
|
auto stat = Ptr(new WfVariableStatement);
|
|
stat->variable = var;
|
|
subBlock->statements.Add(stat);
|
|
}
|
|
{
|
|
auto callback = Ptr(new WfFunctionDeclaration);
|
|
callback->functionKind = WfFunctionKind::Normal;
|
|
callback->anonymity = WfFunctionAnonymity::Anonymous;
|
|
callback->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<void>::CreateTypeInfo().Obj());;
|
|
{
|
|
auto arg = Ptr(new WfFunctionArgument);
|
|
arg->name.value = L"<value>";
|
|
arg->type = GetTypeFromTypeInfo(TypeInfoRetriver<Value>::CreateTypeInfo().Obj());
|
|
callback->arguments.Add(arg);
|
|
}
|
|
auto callbackBlock = Ptr(new WfBlockStatement);
|
|
callback->statement = callbackBlock;
|
|
{
|
|
auto refSubscribee = Ptr(new WfReferenceExpression);
|
|
refSubscribee->name.value = variableName.ToString();
|
|
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = refSubscribee;
|
|
member->name.value = propertyInfo->GetName();
|
|
|
|
auto var = Ptr(new WfVariableDeclaration);
|
|
var->name.value = L"<old>";
|
|
var->expression = member;
|
|
|
|
auto stat = Ptr(new WfVariableStatement);
|
|
stat->variable = var;
|
|
callbackBlock->statements.Add(stat);
|
|
}
|
|
{
|
|
ITypeInfo* propertyType = propertyInfo->GetReturn();
|
|
if (propertyInfo->GetSetter() && propertyInfo->GetSetter()->GetParameterCount() == 1)
|
|
{
|
|
propertyType = propertyInfo->GetSetter()->GetParameter(0)->GetType();
|
|
}
|
|
|
|
auto refValue = Ptr(new WfReferenceExpression);
|
|
refValue->name.value = L"<value>";
|
|
|
|
auto cast = Ptr(new WfTypeCastingExpression);
|
|
cast->strategy = WfTypeCastingStrategy::Strong;
|
|
cast->expression = refValue;
|
|
cast->type = GetTypeFromTypeInfo(propertyType);
|
|
|
|
auto var = Ptr(new WfVariableDeclaration);
|
|
var->name.value = L"<new>";
|
|
var->expression = cast;
|
|
|
|
auto stat = Ptr(new WfVariableStatement);
|
|
stat->variable = var;
|
|
callbackBlock->statements.Add(stat);
|
|
}
|
|
{
|
|
auto refOld = Ptr(new WfReferenceExpression);
|
|
refOld->name.value = L"<old>";
|
|
|
|
auto refNew = Ptr(new WfReferenceExpression);
|
|
refNew->name.value = L"<new>";
|
|
|
|
auto compare = Ptr(new WfBinaryExpression);
|
|
compare->op = WfBinaryOperator::EQ;
|
|
compare->first = refOld;
|
|
compare->second = refNew;
|
|
|
|
auto ifStat = Ptr(new WfIfStatement);
|
|
ifStat->expression = compare;
|
|
callbackBlock->statements.Add(ifStat);
|
|
|
|
auto ifBlock = Ptr(new WfBlockStatement);
|
|
ifStat->trueBranch = ifBlock;
|
|
|
|
auto returnStat = Ptr(new WfReturnStatement);
|
|
ifBlock->statements.Add(returnStat);
|
|
}
|
|
{
|
|
auto refSubscribee = Ptr(new WfReferenceExpression);
|
|
refSubscribee->name.value = variableName.ToString();
|
|
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = refSubscribee;
|
|
member->name.value = propertyInfo->GetName();
|
|
|
|
auto refNew = Ptr(new WfReferenceExpression);
|
|
refNew->name.value = L"<new>";
|
|
|
|
auto assign = Ptr(new WfBinaryExpression);
|
|
assign->op = WfBinaryOperator::Assign;
|
|
assign->first = member;
|
|
assign->second = refNew;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = assign;
|
|
callbackBlock->statements.Add(stat);
|
|
}
|
|
|
|
auto funcExpr = Ptr(new WfFunctionExpression);
|
|
funcExpr->function = callback;
|
|
|
|
auto refBind = Ptr(new WfReferenceExpression);
|
|
refBind->name.value = L"<created-subscription>";
|
|
|
|
auto refEvent = Ptr(new WfMemberExpression);
|
|
refEvent->parent = refBind;
|
|
refEvent->name.value = L"ValueChanged";
|
|
|
|
auto attachExpr = Ptr(new WfAttachEventExpression);
|
|
attachExpr->event = refEvent;
|
|
attachExpr->function = funcExpr;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = attachExpr;
|
|
subBlock->statements.Add(stat);
|
|
}
|
|
{
|
|
auto refThis = Ptr(new WfReferenceExpression);
|
|
refThis->name.value = L"<this>";
|
|
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = refThis;
|
|
member->name.value = L"AddSubscription";
|
|
|
|
auto refBind = Ptr(new WfReferenceExpression);
|
|
refBind->name.value = L"<created-subscription>";
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = member;
|
|
call->arguments.Add(refBind);
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = call;
|
|
subBlock->statements.Add(stat);
|
|
}
|
|
|
|
return subBlock;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_InstallEvalProperty
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfStatement> Workflow_InstallEvalProperty(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, IGuiInstanceLoader* loader, const IGuiInstanceLoader::PropertyInfo& prop, Ptr<GuiInstancePropertyInfo> propInfo, Ptr<workflow::WfExpression> evalExpression, GuiResourceTextPos attPosition, GuiResourceError::List& errors)
|
|
{
|
|
IGuiInstanceLoader::ArgumentMap arguments;
|
|
{
|
|
IGuiInstanceLoader::ArgumentInfo argumentInfo;
|
|
argumentInfo.typeInfo = propInfo->acceptableTypes[0];
|
|
argumentInfo.expression = evalExpression;
|
|
argumentInfo.attPosition = attPosition;
|
|
arguments.Add(prop.propertyName, argumentInfo);
|
|
}
|
|
|
|
return loader->AssignParameters(precompileContext, resolvingResult, prop.typeInfo, variableName, arguments, attPosition, errors);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_InstallEvent
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfStatement> Workflow_InstallEvent(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IEventInfo* eventInfo, const WString& handlerName)
|
|
{
|
|
vint count = eventInfo->GetHandlerType()->GetElementType()->GetGenericArgumentCount() - 1;
|
|
|
|
auto subBlock = Ptr(new WfBlockStatement);
|
|
{
|
|
auto var = Ptr(new WfReferenceExpression);
|
|
var->name.value = variableName.ToString();
|
|
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = var;
|
|
member->name.value = eventInfo->GetName();
|
|
|
|
auto refThis = Ptr(new WfReferenceExpression);
|
|
refThis->name.value = L"<this>";
|
|
|
|
auto handler = Ptr(new WfMemberExpression);
|
|
handler->parent = refThis;
|
|
handler->name.value = handlerName;
|
|
|
|
auto call = Ptr(new WfCallExpression);
|
|
call->function = handler;
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto argument = Ptr(new WfOrderedNameExpression);
|
|
argument->name.value = L"$" + itow(i + 1);
|
|
call->arguments.Add(argument);
|
|
}
|
|
|
|
auto eventHandler = Ptr(new WfOrderedLambdaExpression);
|
|
eventHandler->body = call;
|
|
|
|
auto attachEvent = Ptr(new WfAttachEventExpression);
|
|
attachEvent->event = member;
|
|
attachEvent->function = eventHandler;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = attachEvent;
|
|
subBlock->statements.Add(stat);
|
|
}
|
|
|
|
return subBlock;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_GenerateEventHandler
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfFunctionDeclaration> Workflow_GenerateEventHandler(GuiResourcePrecompileContext& precompileContext, description::IEventInfo* eventInfo)
|
|
{
|
|
auto func = Ptr(new WfFunctionDeclaration);
|
|
func->functionKind = WfFunctionKind::Normal;
|
|
func->anonymity = WfFunctionAnonymity::Anonymous;
|
|
func->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<void>::CreateTypeInfo().Obj());
|
|
|
|
vint count = eventInfo->GetHandlerType()->GetElementType()->GetGenericArgumentCount() - 1;
|
|
bool standardName = false;
|
|
if (count == 2)
|
|
{
|
|
auto senderType = eventInfo->GetHandlerType()->GetElementType()->GetGenericArgument(1)->GetTypeDescriptor();
|
|
auto argumentType = eventInfo->GetHandlerType()->GetElementType()->GetGenericArgument(2)->GetTypeDescriptor();
|
|
if (senderType == GetTypeDescriptor<GuiGraphicsComposition>())
|
|
{
|
|
auto expectedType = GetTypeDescriptor<GuiEventArgs>();
|
|
List<ITypeDescriptor*> types;
|
|
types.Add(argumentType);
|
|
for (vint i = 0; i < types.Count(); i++)
|
|
{
|
|
auto type = types[i];
|
|
if (type == expectedType)
|
|
{
|
|
standardName = true;
|
|
break;
|
|
}
|
|
vint baseCount = type->GetBaseTypeDescriptorCount();
|
|
for (vint j = 0; j < baseCount; j++)
|
|
{
|
|
auto baseType = type->GetBaseTypeDescriptor(j);
|
|
if (!types.Contains(baseType))
|
|
{
|
|
types.Add(baseType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (standardName)
|
|
{
|
|
{
|
|
auto arg = Ptr(new WfFunctionArgument);
|
|
arg->name.value = L"sender";
|
|
arg->type = GetTypeFromTypeInfo(eventInfo->GetHandlerType()->GetElementType()->GetGenericArgument(1));
|
|
func->arguments.Add(arg);
|
|
}
|
|
{
|
|
auto arg = Ptr(new WfFunctionArgument);
|
|
arg->name.value = L"arguments";
|
|
arg->type = GetTypeFromTypeInfo(eventInfo->GetHandlerType()->GetElementType()->GetGenericArgument(2));
|
|
func->arguments.Add(arg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (vint i = 0; i < count; i++)
|
|
{
|
|
auto arg = Ptr(new WfFunctionArgument);
|
|
arg->name.value = L"arg" + itow(i + 1);
|
|
arg->type = GetTypeFromTypeInfo(eventInfo->GetHandlerType()->GetElementType()->GetGenericArgument(i + 1));
|
|
func->arguments.Add(arg);
|
|
}
|
|
}
|
|
|
|
return func;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_InstallEvalEvent
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfStatement> Workflow_InstallEvalEvent(GuiResourcePrecompileContext& precompileContext, types::ResolvingResult& resolvingResult, GlobalStringKey variableName, description::IEventInfo* eventInfo, Ptr<workflow::WfStatement> evalStatement)
|
|
{
|
|
auto func = Workflow_GenerateEventHandler(precompileContext, eventInfo);
|
|
|
|
if (evalStatement.Cast<WfBlockStatement>())
|
|
{
|
|
func->statement = evalStatement;
|
|
}
|
|
else if (evalStatement.Cast<WfCoProviderStatement>())
|
|
{
|
|
func->statement = evalStatement;
|
|
}
|
|
else
|
|
{
|
|
auto funcBlock = Ptr(new WfBlockStatement);
|
|
funcBlock->statements.Add(evalStatement);
|
|
func->statement = funcBlock;
|
|
}
|
|
|
|
auto subBlock = Ptr(new WfBlockStatement);
|
|
|
|
{
|
|
auto eventHandlerLambda = Ptr(new WfFunctionExpression);
|
|
eventHandlerLambda->function = func;
|
|
|
|
auto eventHandler = Ptr(new WfVariableDeclaration);
|
|
eventHandler->name.value = L"<event-handler>";
|
|
eventHandler->expression = eventHandlerLambda;
|
|
|
|
auto stat = Ptr(new WfVariableStatement);
|
|
stat->variable = eventHandler;
|
|
subBlock->statements.Add(stat);
|
|
}
|
|
{
|
|
auto var = Ptr(new WfReferenceExpression);
|
|
var->name.value = variableName.ToString();
|
|
|
|
auto member = Ptr(new WfMemberExpression);
|
|
member->parent = var;
|
|
member->name.value = eventInfo->GetName();
|
|
|
|
auto eventHandler = Ptr(new WfReferenceExpression);
|
|
eventHandler->name.value = L"<event-handler>";
|
|
|
|
auto attachEvent = Ptr(new WfAttachEventExpression);
|
|
attachEvent->event = member;
|
|
attachEvent->function = eventHandler;
|
|
|
|
auto stat = Ptr(new WfExpressionStatement);
|
|
stat->expression = attachEvent;
|
|
subBlock->statements.Add(stat);
|
|
}
|
|
|
|
return subBlock;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\WORKFLOWCODEGEN\GUIINSTANCELOADER_WORKFLOWMODULE.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
using namespace reflection::description;
|
|
using namespace collections;
|
|
|
|
/***********************************************************************
|
|
Workflow_CreateModuleWithUsings
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfModule> Workflow_CreateModuleWithUsings(Ptr<GuiInstanceContext> context, const WString& moduleName)
|
|
{
|
|
auto module = Ptr(new WfModule);
|
|
module->moduleType = WfModuleType::Module;
|
|
module->name.value = moduleName;
|
|
|
|
vint index = context->namespaces.Keys().IndexOf(GlobalStringKey());
|
|
if (index != -1)
|
|
{
|
|
auto nss = context->namespaces.Values()[index];
|
|
for (auto ns : nss->namespaces)
|
|
{
|
|
auto path = Ptr(new WfModuleUsingPath);
|
|
module->paths.Add(path);
|
|
|
|
auto pathCode = ns->prefix + L"*" + ns->postfix;
|
|
auto reading = pathCode.Buffer();
|
|
while (reading)
|
|
{
|
|
auto delimiter = wcsstr(reading, L"::");
|
|
auto begin = reading;
|
|
auto end = delimiter ? delimiter : begin + wcslen(reading);
|
|
|
|
auto wildcard = wcschr(reading, L'*');
|
|
if (wildcard >= end)
|
|
{
|
|
wildcard = nullptr;
|
|
}
|
|
|
|
auto item = Ptr(new WfModuleUsingItem);
|
|
path->items.Add(item);
|
|
if (wildcard)
|
|
{
|
|
if (begin < wildcard)
|
|
{
|
|
auto fragment = Ptr(new WfModuleUsingNameFragment);
|
|
item->fragments.Add(fragment);
|
|
fragment->name.value = WString::CopyFrom(begin, vint(wildcard - begin));
|
|
}
|
|
{
|
|
auto fragment = Ptr(new WfModuleUsingWildCardFragment);
|
|
item->fragments.Add(fragment);
|
|
}
|
|
if (wildcard + 1 < end)
|
|
{
|
|
auto fragment = Ptr(new WfModuleUsingNameFragment);
|
|
item->fragments.Add(fragment);
|
|
fragment->name.value = WString::CopyFrom(wildcard + 1, vint(end - wildcard - 1));
|
|
}
|
|
}
|
|
else if (begin < end)
|
|
{
|
|
auto fragment = Ptr(new WfModuleUsingNameFragment);
|
|
item->fragments.Add(fragment);
|
|
fragment->name.value = WString::CopyFrom(begin, vint(end - begin));
|
|
}
|
|
|
|
if (delimiter)
|
|
{
|
|
reading = delimiter + 2;
|
|
}
|
|
else
|
|
{
|
|
reading = nullptr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return module;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_InstallClass
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfClassDeclaration> Workflow_InstallClass(const WString& className, Ptr<workflow::WfModule> module)
|
|
{
|
|
auto decls = &module->declarations;
|
|
auto reading = className.Buffer();
|
|
while (true)
|
|
{
|
|
auto delimiter = wcsstr(reading, L"::");
|
|
if (delimiter)
|
|
{
|
|
auto ns = Ptr(new WfNamespaceDeclaration);
|
|
ns->name.value = WString::CopyFrom(reading, delimiter - reading);
|
|
decls->Add(ns);
|
|
decls = &ns->declarations;
|
|
}
|
|
else
|
|
{
|
|
auto ctorClass = Ptr(new WfClassDeclaration);
|
|
ctorClass->kind = WfClassKind::Class;
|
|
ctorClass->constructorType = WfConstructorType::Undefined;
|
|
ctorClass->name.value = reading;
|
|
decls->Add(ctorClass);
|
|
return ctorClass;
|
|
}
|
|
reading = delimiter + 2;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_InstallCtorClass
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfBlockStatement> Workflow_InstallCtorClass(types::ResolvingResult& resolvingResult, Ptr<workflow::WfModule> module)
|
|
{
|
|
auto ctorClass = Workflow_InstallClass(resolvingResult.context->className + L"Constructor", module);
|
|
Workflow_CreateVariablesForReferenceValues(ctorClass, resolvingResult);
|
|
|
|
auto thisParam = Ptr(new WfFunctionArgument);
|
|
thisParam->name.value = L"<this>";
|
|
thisParam->type = GetTypeFromTypeInfo(resolvingResult.rootTypeInfo.typeInfo.Obj());
|
|
|
|
auto block = Ptr(new WfBlockStatement);
|
|
|
|
auto func = Ptr(new WfFunctionDeclaration);
|
|
func->functionKind = WfFunctionKind::Normal;
|
|
func->anonymity = WfFunctionAnonymity::Named;
|
|
func->arguments.Add(thisParam);
|
|
func->returnType = GetTypeFromTypeInfo(TypeInfoRetriver<void>::CreateTypeInfo().Obj());
|
|
func->statement = block;
|
|
|
|
{
|
|
List<WString> fragments;
|
|
SplitTypeName(resolvingResult.context->className, fragments);
|
|
func->name.value = L"<" + From(fragments).Aggregate([](const WString& a, const WString& b) {return a + L"-" + b; }) + L">Initialize";
|
|
}
|
|
{
|
|
auto att = Ptr(new WfAttribute);
|
|
att->category.value = L"cpp";
|
|
att->name.value = L"Protected";
|
|
func->attributes.Add(att);
|
|
}
|
|
|
|
ctorClass->declarations.Add(func);
|
|
return block;
|
|
}
|
|
|
|
/***********************************************************************
|
|
Variable
|
|
***********************************************************************/
|
|
|
|
void Workflow_CreatePointerVariable(Ptr<workflow::WfClassDeclaration> ctorClass, GlobalStringKey name, description::ITypeInfo* typeInfo)
|
|
{
|
|
auto var = Ptr(new WfVariableDeclaration);
|
|
var->name.value = name.ToString();
|
|
var->type = GetTypeFromTypeInfo(typeInfo);
|
|
|
|
{
|
|
auto att = Ptr(new WfAttribute);
|
|
att->category.value = L"cpp";
|
|
att->name.value = L"Protected";
|
|
var->attributes.Add(att);
|
|
}
|
|
|
|
if (!var->type)
|
|
{
|
|
if (auto ctors = typeInfo->GetTypeDescriptor()->GetConstructorGroup())
|
|
{
|
|
if (ctors->GetMethodCount() > 0)
|
|
{
|
|
auto ctor = ctors->GetMethod(0);
|
|
var->type = GetTypeFromTypeInfo(ctor->GetReturn());
|
|
}
|
|
}
|
|
}
|
|
|
|
var->expression = CreateDefaultValue(typeInfo);
|
|
ctorClass->declarations.Add(var);
|
|
}
|
|
|
|
void Workflow_CreateVariablesForReferenceValues(Ptr<workflow::WfClassDeclaration> ctorClass, types::ResolvingResult& resolvingResult)
|
|
{
|
|
const auto& typeInfos = resolvingResult.typeInfos;
|
|
for (vint i = 0; i < typeInfos.Count(); i++)
|
|
{
|
|
auto key = typeInfos.Keys()[i];
|
|
auto value = typeInfos.Values()[i].typeInfo.Obj();
|
|
Workflow_CreatePointerVariable(ctorClass, key, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\WORKFLOWCODEGEN\GUIINSTANCELOADER_WORKFLOWPARSER.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace stream;
|
|
using namespace reflection::description;
|
|
using namespace workflow;
|
|
using namespace workflow::analyzer;
|
|
|
|
/***********************************************************************
|
|
Parser
|
|
***********************************************************************/
|
|
|
|
template<typename T>
|
|
Ptr<T> Workflow_Parse(GuiResourcePrecompileContext& precompileContext, const WString& parserName, GuiResourceLocation location, const WString& code, GuiResourceTextPos position, collections::List<GuiResourceError>& errors, glr::ParsingTextPos availableAfter)
|
|
{
|
|
vint errorCount = errors.Count();
|
|
auto parser = GetParserManager()->GetParser<T>(parserName);
|
|
auto result = parser->Parse(location, code, position, errors);
|
|
|
|
if (availableAfter.row != 0 || availableAfter.column != 0)
|
|
{
|
|
for (vint i = errorCount; i < errors.Count(); i++)
|
|
{
|
|
auto& error = errors[i];
|
|
if (error.position.row > position.row)
|
|
{
|
|
error.position.row -= availableAfter.row;
|
|
}
|
|
else if (error.position.row == position.row && error.position.column >= position.column)
|
|
{
|
|
error.position.column -= availableAfter.column;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result)
|
|
{
|
|
Workflow_RecordScriptPosition(precompileContext, position, result, availableAfter);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Ptr<workflow::WfType> Workflow_ParseType(GuiResourcePrecompileContext& precompileContext, GuiResourceLocation location, const WString& code, GuiResourceTextPos position, collections::List<GuiResourceError>& errors, glr::ParsingTextPos availableAfter)
|
|
{
|
|
return Workflow_Parse<WfType>(precompileContext, L"WORKFLOW-TYPE", location, code, position, errors, availableAfter);
|
|
}
|
|
|
|
Ptr<workflow::WfExpression> Workflow_ParseExpression(GuiResourcePrecompileContext& precompileContext, GuiResourceLocation location, const WString& code, GuiResourceTextPos position, collections::List<GuiResourceError>& errors, glr::ParsingTextPos availableAfter)
|
|
{
|
|
return Workflow_Parse<WfExpression>(precompileContext, L"WORKFLOW-EXPRESSION", location, code, position, errors, availableAfter);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> Workflow_ParseStatement(GuiResourcePrecompileContext& precompileContext, GuiResourceLocation location, const WString& code, GuiResourceTextPos position, collections::List<GuiResourceError>& errors, glr::ParsingTextPos availableAfter)
|
|
{
|
|
return Workflow_Parse<WfStatement>(precompileContext, L"WORKFLOW-STATEMENT", location, code, position, errors, availableAfter);
|
|
}
|
|
|
|
Ptr<workflow::WfStatement> Workflow_ParseCoProviderStatement(GuiResourcePrecompileContext& precompileContext, GuiResourceLocation location, const WString& code, GuiResourceTextPos position, collections::List<GuiResourceError>& errors, glr::ParsingTextPos availableAfter)
|
|
{
|
|
return Workflow_Parse<WfStatement>(precompileContext, L"WORKFLOW-COPROVIDER-STATEMENT", location, code, position, errors, availableAfter);
|
|
}
|
|
|
|
Ptr<workflow::WfModule> Workflow_ParseModule(GuiResourcePrecompileContext& precompileContext, GuiResourceLocation location, const WString& code, GuiResourceTextPos position, collections::List<GuiResourceError>& errors, glr::ParsingTextPos availableAfter)
|
|
{
|
|
return Workflow_Parse<WfModule>(precompileContext, L"WORKFLOW-MODULE", location, code, position, errors, availableAfter);
|
|
}
|
|
|
|
/***********************************************************************
|
|
Workflow_ModuleToString
|
|
***********************************************************************/
|
|
|
|
WString Workflow_ModuleToString(Ptr<workflow::WfModule> module)
|
|
{
|
|
return GenerateToStream([&](StreamWriter& writer)
|
|
{
|
|
WfPrint(module, L"", writer);
|
|
});
|
|
}
|
|
|
|
/***********************************************************************
|
|
Converter
|
|
***********************************************************************/
|
|
|
|
Ptr<workflow::WfExpression> Workflow_ParseTextValue(GuiResourcePrecompileContext& precompileContext, description::ITypeDescriptor* typeDescriptor, GuiResourceLocation location, const WString& textValue, GuiResourceTextPos position, collections::List<GuiResourceError>& errors)
|
|
{
|
|
if (typeDescriptor == description::GetTypeDescriptor<WString>())
|
|
{
|
|
auto valueExpr = Ptr(new WfStringExpression);
|
|
valueExpr->value.value = textValue;
|
|
return valueExpr;
|
|
}
|
|
else if (typeDescriptor == description::GetTypeDescriptor<bool>())
|
|
{
|
|
bool value = false;
|
|
if (!TypedValueSerializerProvider<bool>::Deserialize(textValue, value)) return nullptr;
|
|
auto valueExpr = Ptr(new WfLiteralExpression);
|
|
valueExpr->value = value ? WfLiteralValue::True : WfLiteralValue::False;
|
|
return valueExpr;
|
|
}
|
|
#define INTEGER_BRANCH(TYPE) \
|
|
else if (typeDescriptor == description::GetTypeDescriptor<TYPE>()) \
|
|
{ \
|
|
auto valueExpr = Ptr(new WfIntegerExpression); \
|
|
valueExpr->value.value = textValue; \
|
|
auto type = Ptr(new TypeDescriptorTypeInfo(typeDescriptor, TypeInfoHint::Normal)); \
|
|
auto infer = Ptr(new WfInferExpression); \
|
|
infer->type = GetTypeFromTypeInfo(type.Obj()); \
|
|
infer->expression = valueExpr; \
|
|
return infer; \
|
|
}
|
|
INTEGER_BRANCH(vint8_t)
|
|
INTEGER_BRANCH(vint16_t)
|
|
INTEGER_BRANCH(vint32_t)
|
|
INTEGER_BRANCH(vint64_t)
|
|
INTEGER_BRANCH(vuint8_t)
|
|
INTEGER_BRANCH(vuint16_t)
|
|
INTEGER_BRANCH(vuint32_t)
|
|
INTEGER_BRANCH(vuint64_t)
|
|
#undef INTEGER_BRANCH
|
|
|
|
#define FLOATING_BRANCH(TYPE) \
|
|
else if (typeDescriptor == description::GetTypeDescriptor<TYPE>()) \
|
|
{ \
|
|
auto valueExpr = Ptr(new WfFloatingExpression); \
|
|
valueExpr->value.value = textValue; \
|
|
auto type = Ptr(new TypeDescriptorTypeInfo(typeDescriptor, TypeInfoHint::Normal)); \
|
|
auto infer = Ptr(new WfInferExpression); \
|
|
infer->type = GetTypeFromTypeInfo(type.Obj()); \
|
|
infer->expression = valueExpr; \
|
|
return infer; \
|
|
}
|
|
FLOATING_BRANCH(float)
|
|
FLOATING_BRANCH(double)
|
|
#undef FLOATING_BRANCH
|
|
|
|
else if (typeDescriptor->GetSerializableType())
|
|
{
|
|
auto str = Ptr(new WfStringExpression);
|
|
str->value.value = textValue;
|
|
|
|
auto type = Ptr(new TypeDescriptorTypeInfo(typeDescriptor, TypeInfoHint::Normal));
|
|
|
|
auto cast = Ptr(new WfTypeCastingExpression);
|
|
cast->type = GetTypeFromTypeInfo(type.Obj());
|
|
cast->strategy = WfTypeCastingStrategy::Strong;
|
|
cast->expression = str;
|
|
|
|
return cast;
|
|
}
|
|
else if (typeDescriptor->GetTypeDescriptorFlags() == TypeDescriptorFlags::Struct)
|
|
{
|
|
if (auto valueExpr = Workflow_ParseExpression(precompileContext, location, L"{" + textValue + L"}", position, errors, { 0,1 })) // {
|
|
{
|
|
auto type = Ptr(new TypeDescriptorTypeInfo(typeDescriptor, TypeInfoHint::Normal));
|
|
|
|
auto infer = Ptr(new WfInferExpression);
|
|
infer->type = GetTypeFromTypeInfo(type.Obj());
|
|
infer->expression = valueExpr;
|
|
|
|
return infer;
|
|
}
|
|
return nullptr;
|
|
}
|
|
else if ((typeDescriptor->GetTypeDescriptorFlags() & TypeDescriptorFlags::EnumType) != TypeDescriptorFlags::Undefined)
|
|
{
|
|
if (auto valueExpr = Workflow_ParseExpression(precompileContext, location, L"(" + textValue + L")", position, errors, { 0,1 })) // {
|
|
{
|
|
auto type = Ptr(new TypeDescriptorTypeInfo(typeDescriptor, TypeInfoHint::Normal));
|
|
|
|
auto infer = Ptr(new WfInferExpression);
|
|
infer->type = GetTypeFromTypeInfo(type.Obj());
|
|
infer->expression = valueExpr;
|
|
|
|
return infer;
|
|
}
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
CHECK_FAIL(L"vl::presentation::Workflow_ParseTextValue(ITypeDescriptor*, const WString&, GuiResourceError::List&)#This is not a value type.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
.\WORKFLOWCODEGEN\GUIINSTANCELOADER_WORKFLOWSCRIPTPOSITION.CPP
|
|
***********************************************************************/
|
|
|
|
namespace vl
|
|
{
|
|
namespace presentation
|
|
{
|
|
using namespace collections;
|
|
using namespace workflow;
|
|
|
|
/***********************************************************************
|
|
WorkflowScriptPositionVisitor
|
|
***********************************************************************/
|
|
|
|
class WorkflowScriptPositionVisitor : public workflow::traverse_visitor::AstVisitor
|
|
{
|
|
public:
|
|
GuiResourcePrecompileContext& context;
|
|
GuiResourceTextPos position;
|
|
glr::ParsingTextPos availableAfter;
|
|
Ptr<types::ScriptPosition> sp;
|
|
|
|
WorkflowScriptPositionVisitor(GuiResourcePrecompileContext& _context, GuiResourceTextPos _position, glr::ParsingTextPos _availableAfter)
|
|
:context(_context)
|
|
, position(_position)
|
|
, availableAfter(_availableAfter)
|
|
{
|
|
vint index = context.additionalProperties.Keys().IndexOf(nullptr);
|
|
if (index == -1)
|
|
{
|
|
context.additionalProperties.Add(nullptr, Ptr(new types::ScriptPosition));
|
|
}
|
|
sp = context.additionalProperties[nullptr].Cast<types::ScriptPosition>();
|
|
}
|
|
|
|
void Traverse(glr::ParsingAstBase* node) override
|
|
{
|
|
if (!sp->nodePositions.Keys().Contains(node))
|
|
{
|
|
auto pos = node->codeRange.start;
|
|
if (pos.row == availableAfter.row && pos.column > availableAfter.column)
|
|
{
|
|
pos.column -= availableAfter.column;
|
|
}
|
|
else if (pos.row > availableAfter.row)
|
|
{
|
|
pos.row -= availableAfter.row;
|
|
}
|
|
|
|
types::ScriptPositionRecord record;
|
|
record.position = position;
|
|
record.availableAfter = availableAfter;
|
|
if (pos.row < 0 || pos.column < 0)
|
|
{
|
|
record.computedPosition = position;
|
|
}
|
|
else if (pos.row == 0)
|
|
{
|
|
record.computedPosition = { position.originalLocation,{position.row,position.column + pos.column} };
|
|
}
|
|
else
|
|
{
|
|
record.computedPosition = { position.originalLocation,{ position.row + pos.row,pos.column } };
|
|
}
|
|
|
|
sp->nodePositions.Add(Ptr(node), record);
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************
|
|
WorkflowCompiler_ScriptPosition
|
|
***********************************************************************/
|
|
|
|
void Workflow_RecordScriptPosition(GuiResourcePrecompileContext& context, GuiResourceTextPos position, Ptr<workflow::WfType> node, glr::ParsingTextPos availableAfter)
|
|
{
|
|
WorkflowScriptPositionVisitor(context, position, availableAfter).InspectInto(node.Obj());
|
|
}
|
|
|
|
void Workflow_RecordScriptPosition(GuiResourcePrecompileContext& context, GuiResourceTextPos position, Ptr<workflow::WfExpression> node, glr::ParsingTextPos availableAfter)
|
|
{
|
|
WorkflowScriptPositionVisitor(context, position, availableAfter).InspectInto(node.Obj());
|
|
}
|
|
|
|
void Workflow_RecordScriptPosition(GuiResourcePrecompileContext& context, GuiResourceTextPos position, Ptr<workflow::WfStatement> node, glr::ParsingTextPos availableAfter)
|
|
{
|
|
WorkflowScriptPositionVisitor(context, position, availableAfter).InspectInto(node.Obj());
|
|
}
|
|
|
|
void Workflow_RecordScriptPosition(GuiResourcePrecompileContext& context, GuiResourceTextPos position, Ptr<workflow::WfDeclaration> node, glr::ParsingTextPos availableAfter)
|
|
{
|
|
WorkflowScriptPositionVisitor(context, position, availableAfter).InspectInto(node.Obj());
|
|
}
|
|
|
|
void Workflow_RecordScriptPosition(GuiResourcePrecompileContext& context, GuiResourceTextPos position, Ptr<workflow::WfModule> node, glr::ParsingTextPos availableAfter)
|
|
{
|
|
WorkflowScriptPositionVisitor(context, position, availableAfter).InspectInto(node.Obj());
|
|
}
|
|
|
|
Ptr<types::ScriptPosition> Workflow_GetScriptPosition(GuiResourcePrecompileContext& context)
|
|
{
|
|
vint index = context.additionalProperties.Keys().IndexOf(nullptr);
|
|
if (index == -1) return nullptr;
|
|
return context.additionalProperties.Values()[index].Cast<types::ScriptPosition>();
|
|
}
|
|
|
|
void Workflow_ClearScriptPosition(GuiResourcePrecompileContext& context)
|
|
{
|
|
context.additionalProperties.Remove(nullptr);
|
|
}
|
|
}
|
|
}
|