/* * This source file is part of RmlUi, the HTML/CSS Interface Middleware * * For the latest information, see http://github.com/mikke89/RmlUi * * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd * Copyright (c) 2019 The RmlUi Team, and contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ #include "../Common/TestsShell.h" #include #include #include #include #include using namespace Rml; namespace { static const String document_rml = R"( Test

{{ test }}

{{ str1.val }}

{{ str2.val }}

{{ str3.val }}

{{ test2.val }}

Basic

{{ basic.a }}

{{ basic.b }}

{{ basic.c }}

{{ basic.d }}

{{ basic.e }}

{{ basic.f }}

{{ basic.g }}

{{ basic.h }}

Wrapped

{{ wrapped.a.val }}

{{ wrapped.b.val }}

{{ wrapped.c.val }}

{{ wrapped.d.val }}

{{ wrapped.e.val }}

{{ wrapped.f.val }}

{{ wrapped.g.val }}

{{ wrapped.h.val }}

Pointed

{{ pointed.a.val }}

{{ pointed.e.val }}

{{ pointed.f.val }}

{{ pointed.g.val }}

{{ pointed.h.val }}

ConstPointed

{{ const_pointed.a.val }}

{{ const_pointed.e.val }}

{{ const_pointed.f.val }}

{{ const_pointed.g.val }}

{{ const_pointed.h.val }}

Arrays

{{ it }}

{{ it }}

{{ it }}

{{ it.val }}

{{ it.val }}

{{ it.val }}

{{ it.val }}

)"; struct StringWrap { StringWrap(String val = "wrap_default") : val(val) {} String val; }; StringWrap gStr0 = StringWrap("obj"); StringWrap* gStr1 = new StringWrap("raw"); UniquePtr gStr2 = MakeUnique("unique"); SharedPtr gStr3 = MakeShared("shared"); const StringWrap* gStr4 = new StringWrap("const raw"); const int* const_ptr_test = new int(5); struct Basic { int a = 1; int* b = new int(2); const int* c = new int(3); int GetD() { return 4; } int& GetE() const { static int e = 5; return e; } int* GetF() { static int f = 6; return &f; } const int& GetG() { static int g = 7; return g; } const int* GetH() { static int h = 8; return &h; } }; struct Wrapped { StringWrap a = { "a" }; StringWrap* b = new StringWrap("b"); const StringWrap* c = new StringWrap("c"); // Illegal: Must return by reference, or return scalar value. StringWrap GetD() { return { "d" }; } StringWrap& GetE() { static StringWrap e = { "e" }; return e; } StringWrap* GetF() { static StringWrap f = { "f" }; return &f; } const StringWrap& GetG() { static StringWrap g = { "g" }; return g; } const StringWrap* GetH() { static StringWrap h = { "h" }; return &h; } }; using StringWrapPtr = UniquePtr; struct Pointed { StringWrapPtr a = MakeUnique("a"); // We disallow recursive pointer types (pointer to pointer) // Invalid: StringWrapPtr* b = new StringWrapPtr(new StringWrap("b")); const StringWrapPtr* c = new StringWrapPtr(new StringWrap("c")); StringWrapPtr GetD() { return MakeUnique("d"); } // -- End Invalid StringWrapPtr& GetE() { static StringWrapPtr e = MakeUnique("e"); return e; } StringWrapPtr* GetF() { static StringWrapPtr f = MakeUnique("f"); return &f; } const StringWrapPtr& GetG() { static StringWrapPtr g = MakeUnique("g"); return g; } const StringWrapPtr* GetH() { static StringWrapPtr h = MakeUnique("h"); return &h; } }; using StringWrapConstPtr = UniquePtr; struct ConstPointed { StringWrapConstPtr a = MakeUnique("a"); // We disallow recursive pointer types (pointer to pointer) // -- Invalid StringWrapConstPtr* b = new StringWrapConstPtr(new StringWrap("b")); const StringWrapConstPtr* c = new StringWrapConstPtr(new StringWrap("c")); StringWrapConstPtr GetD() { return MakeUnique("d"); } // -- End Invalid StringWrapConstPtr& GetE() { static StringWrapConstPtr e = MakeUnique("e"); return e; } StringWrapConstPtr* GetF() { static StringWrapConstPtr f = MakeUnique("f"); return &f; } const StringWrapConstPtr& GetG() { static StringWrapConstPtr g = MakeUnique("g"); return g; } const StringWrapConstPtr* GetH() { static StringWrapConstPtr h = MakeUnique("h"); return &h; } }; struct Arrays { Vector a = { 10, 11, 12 }; Vector b = { new int(20), new int(21), new int(22) }; Vector c = { new int(30), new int(31), new int(32) }; Vector d = { StringWrap("d1"), StringWrap("d2"), StringWrap("d3") }; Vector e = { new StringWrap("e1"), new StringWrap("e2"), new StringWrap("e3") }; Vector f; Vector g; Arrays() { f.emplace_back(MakeUnique("f1")); f.emplace_back(MakeUnique("f2")); f.emplace_back(MakeUnique("f3")); g.emplace_back(MakeUnique("g1")); g.emplace_back(MakeUnique("g2")); g.emplace_back(MakeUnique("g3")); } }; DataModelHandle model_handle; bool InitializeDataBindings(Context* context) { Rml::DataModelConstructor constructor = context->CreateDataModel("basics"); if (!constructor) return false; if (auto handle = constructor.RegisterStruct()) { handle.RegisterMember("val", &StringWrap::val); } constructor.Bind("test", &const_ptr_test); constructor.Bind("test2", &gStr4); constructor.Bind("str0", &gStr0); constructor.Bind("str1", &gStr1); constructor.Bind("str2", &gStr2); constructor.Bind("str3", &gStr3); if (auto handle = constructor.RegisterStruct()) { handle.RegisterMember("a", &Basic::a); handle.RegisterMember("b", &Basic::b); handle.RegisterMember("c", &Basic::c); handle.RegisterMember("d", &Basic::GetD); handle.RegisterMember("e", &Basic::GetE); handle.RegisterMember("f", &Basic::GetF); handle.RegisterMember("g", &Basic::GetG); handle.RegisterMember("h", &Basic::GetH); } constructor.Bind("basic", new Basic); if (auto handle = constructor.RegisterStruct()) { handle.RegisterMember("a", &Wrapped::a); handle.RegisterMember("b", &Wrapped::b); handle.RegisterMember("c", &Wrapped::c); //handle.RegisterMember("d", &Wrapped::GetD); handle.RegisterMember("e", &Wrapped::GetE); handle.RegisterMember("f", &Wrapped::GetF); handle.RegisterMember("g", &Wrapped::GetG); handle.RegisterMember("h", &Wrapped::GetH); } constructor.Bind("wrapped", new Wrapped); if (auto handle = constructor.RegisterStruct()) { handle.RegisterMember("a", &Pointed::a); //handle.RegisterMember("b", &Pointed::b); //handle.RegisterMember("c", &Pointed::c); //handle.RegisterMember("d", &Pointed::GetD); handle.RegisterMember("e", &Pointed::GetE); handle.RegisterMember("f", &Pointed::GetF); handle.RegisterMember("g", &Pointed::GetG); handle.RegisterMember("h", &Pointed::GetH); } constructor.Bind("pointed", new Pointed); if (auto handle = constructor.RegisterStruct()) { handle.RegisterMember("a", &ConstPointed::a); //handle.RegisterMember("b", &ConstPointed::b); //handle.RegisterMember("c", &ConstPointed::c); //handle.RegisterMemberGetter("d", &ConstPointed::GetD); handle.RegisterMember("e", &ConstPointed::GetE); handle.RegisterMember("f", &ConstPointed::GetF); handle.RegisterMember("g", &ConstPointed::GetG); handle.RegisterMember("h", &ConstPointed::GetH); } constructor.Bind("const_pointed", new ConstPointed); constructor.RegisterArray(); constructor.RegisterArray(); constructor.RegisterArray(); constructor.RegisterArray(); constructor.RegisterArray(); constructor.RegisterArray(); constructor.RegisterArray(); if (auto handle = constructor.RegisterStruct()) { handle.RegisterMember("a", &Arrays::a); handle.RegisterMember("b", &Arrays::b); handle.RegisterMember("c", &Arrays::c); handle.RegisterMember("d", &Arrays::d); handle.RegisterMember("e", &Arrays::e); handle.RegisterMember("f", &Arrays::f); handle.RegisterMember("g", &Arrays::g); } constructor.Bind("arrays", new Arrays); model_handle = constructor.GetModelHandle(); return true; } } // Anonymous namespace TEST_CASE("databinding") { Context* context = TestsShell::GetContext(); REQUIRE(context); REQUIRE(InitializeDataBindings(context)); ElementDocument* document = context->LoadDocumentFromMemory(document_rml); REQUIRE(document); document->Show(); context->Update(); context->Render(); TestsShell::RenderLoop(); document->Close(); TestsShell::ShutdownShell(); }