Sfoglia il codice sorgente

Add new data-alias attribute to make templates work with outside variables (#432)

Maximilian Stark 2 anni fa
parent
commit
4db7a3b1f4

+ 19 - 0
Samples/assets/data-window.rml

@@ -0,0 +1,19 @@
+<template name="data-window" content="content">
+<head>
+	<link type="text/rcss" href="rml.rcss"/>
+	<link type="text/rcss" href="invader.rcss"/>
+</head>
+<body class="window">
+	<div id="title_bar">
+		<handle move_target="#document">
+			<div id="icon"></div>
+			<span class="title">{{ title }}</span>
+		</handle>
+	</div>
+	<div id="window">
+		<div id="content">
+		</div>
+	</div>
+	<handle size_target="#document" style="position: absolute; width: 16dp; height: 16dp; bottom: 0px; right: 0px; cursor: resize;"></handle>
+</body>
+</template>

+ 28 - 0
Source/Core/DataViewDefault.cpp

@@ -605,4 +605,32 @@ void DataViewFor::Release()
 	delete this;
 }
 
+DataViewAlias::DataViewAlias(Element* element) : DataView(element, 0) {}
+
+StringList DataViewAlias::GetVariableNameList() const
+{
+	return variables;
+}
+
+bool DataViewAlias::Update(DataModel&)
+{
+	return false;
+}
+
+bool DataViewAlias::Initialize(DataModel& model, Element* element, const String& expression, const String& modifier)
+{
+	auto address = model.ResolveAddress(expression, element);
+	if (address.empty())
+		return false;
+
+	variables.push_back(modifier);
+	model.InsertAlias(element, modifier, address);
+	return true;
+}
+
+void DataViewAlias::Release()
+{
+	delete this;
+}
+
 } // namespace Rml

+ 14 - 0
Source/Core/DataViewDefault.h

@@ -181,5 +181,19 @@ private:
 	ElementList elements;
 };
 
+class DataViewAlias final : public DataView {
+public:
+	DataViewAlias(Element* element);
+	virtual StringList GetVariableNameList() const override;
+	bool Update(DataModel& model) override;
+	bool Initialize(DataModel& model, Element* element, const String& expression, const String& modifier) override;
+
+protected:
+	void Release() override;
+
+private:
+	StringList variables;
+};
+
 } // namespace Rml
 #endif

+ 2 - 0
Source/Core/Factory.cpp

@@ -182,6 +182,7 @@ struct DefaultInstancers {
 	DataViewInstancerDefault<DataViewText> data_view_text;
 	DataViewInstancerDefault<DataViewValue> data_view_value;
 	DataViewInstancerDefault<DataViewChecked> data_view_checked;
+	DataViewInstancerDefault<DataViewAlias> data_view_alias;
 
 	DataViewInstancerDefault<DataViewFor> structural_data_view_for;
 
@@ -275,6 +276,7 @@ bool Factory::Initialise()
 	RegisterDataViewInstancer(&default_instancers->data_view_text,           "text",    false);
 	RegisterDataViewInstancer(&default_instancers->data_view_value,          "value",   false);
 	RegisterDataViewInstancer(&default_instancers->data_view_checked,        "checked", false);
+	RegisterDataViewInstancer(&default_instancers->data_view_alias,          "alias",   false);
 	RegisterDataViewInstancer(&default_instancers->structural_data_view_for, "for",     true );
 
 	// Data binding controllers

+ 48 - 0
Tests/Source/UnitTests/DataBinding.cpp

@@ -148,6 +148,28 @@ static const String inside_string_rml = R"(
 </rml>	
 )";
 
+static const String aliasing_rml = R"(
+<rml>
+<head>
+	<title>Test</title>
+	<link type="text/rcss" href="/assets/rml.rcss"/>
+	<link type="text/template" href="/assets/data-window.rml"/>
+</head>
+
+<body data-model="basics">
+<p>{{ i0 }}</p>
+<p data-alias-differentname="i0">{{ differentname }}</p>
+<div data-alias-title="s0" id="w1">
+	<template src="data-window"></template>
+</div>
+
+<div data-alias-title="s1" id="w2">
+	<template src="data-window"></template>
+</div>
+</body>
+</rml>	
+)";
+
 struct StringWrap
 {
 	StringWrap(String val = "wrap_default") : val(val) {}
@@ -448,5 +470,31 @@ TEST_CASE("databinding.inside_string")
 
 	document->Close();
 
+	TestsShell::ShutdownShell();
+}
+TEST_CASE("databinding.aliasing")
+{
+	Context* context = TestsShell::GetContext();
+	REQUIRE(context);
+
+	REQUIRE(InitializeDataBindings(context));
+
+	ElementDocument* document = context->LoadDocumentFromMemory(aliasing_rml);
+	REQUIRE(document);
+	document->Show();
+
+	context->Update();
+	context->Render();
+
+	TestsShell::RenderLoop();
+
+	CHECK(document->QuerySelector("p:nth-child(1)")->GetInnerRML() == document->QuerySelector("p:nth-child(2)")->GetInnerRML());
+	REQUIRE(document->QuerySelector("#w1 .title"));
+	REQUIRE(document->QuerySelector("#w2 .title"));
+	CHECK(document->QuerySelector("#w1 .title")->GetInnerRML() == "s0");
+	CHECK(document->QuerySelector("#w2 .title")->GetInnerRML() == "s1");
+
+	document->Close();
+
 	TestsShell::ShutdownShell();
 }