Browse Source

Merge branch 'master' into data_binding

Michael Ragazzon 5 years ago
parent
commit
cc5cbbebe8

+ 10 - 4
Include/RmlUi/Core/ElementDocument.h

@@ -113,11 +113,17 @@ public:
 	/// @return True if the document is hogging focus.
 	bool IsModal() const;
 
-	/// Load a script into the document. Note that the base implementation does nothing, scripting language addons hook
+	/// Load a inline script into the document. Note that the base implementation does nothing, scripting language addons hook
 	/// this method.
-	/// @param[in] stream Stream of code to process.
-	/// @param[in] source_name Name of the the script the source comes from, useful for debug information.
-	virtual void LoadScript(Stream* stream, const String& source_name);
+	/// @param[in] content The script content.
+	/// @param[in] source_path Path of the script the source comes from, useful for debug information.
+	/// @param[in] source_line Line of the script the source comes from, useful for debug information.
+	virtual void LoadInlineScript(const String& content, const String& source_path, int source_line);
+
+	/// Load a external script into the document. Note that the base implementation does nothing, scripting language addons hook
+	/// this method.
+	/// @param[in] source_path The script file path.
+	virtual void LoadExternalScript(const String& source_path);
 
 	/// Updates the document, including its layout. Users must call this manually before requesting information such as 
 	/// size or position of an element if any element in the document was recently changed, unless Context::Update has

+ 2 - 0
Include/RmlUi/Core/Elements/ElementFormControlInput.h

@@ -70,6 +70,8 @@ protected:
 	void OnRender() override;
 	/// Calls the element's underlying type.
 	void OnResize() override;
+	/// Calls the element's underlying type.
+	void OnLayout() override;
 
 	/// Checks for necessary functional changes in the control as a result of changed attributes.
 	/// @param[in] changed_attributes The list of changed attributes.

+ 7 - 7
Source/Core/DocumentHeader.cpp

@@ -43,15 +43,10 @@ void DocumentHeader::MergeHeader(const DocumentHeader& header)
 	if (source.empty())
 		source = header.source;
 
-	// Combine internal data	
-	rcss_inline.insert(rcss_inline.end(), header.rcss_inline.begin(), header.rcss_inline.end());	
-	rcss_inline_line_numbers.insert(rcss_inline_line_numbers.end(), header.rcss_inline_line_numbers.begin(), header.rcss_inline_line_numbers.end());
-	scripts_inline.insert(scripts_inline.end(), header.scripts_inline.begin(), header.scripts_inline.end());
-	
 	// Combine external data, keeping relative paths
 	MergePaths(template_resources, header.template_resources, header.source);
-	MergePaths(rcss_external, header.rcss_external, header.source);
-	MergePaths(scripts_external, header.scripts_external, header.source);
+	MergeResources(rcss, header.rcss);
+	MergeResources(scripts, header.scripts);
 }
 
 void DocumentHeader::MergePaths(StringList& target, const StringList& source, const String& source_path)
@@ -65,4 +60,9 @@ void DocumentHeader::MergePaths(StringList& target, const StringList& source, co
 	}
 }
 
+void DocumentHeader::MergeResources(ResourceList& target, const ResourceList& source)
+{
+	target.insert(target.end(), source.begin(), source.end());
+}
+
 } // namespace Rml

+ 15 - 9
Source/Core/DocumentHeader.h

@@ -52,16 +52,19 @@ public:
 	/// A list of template resources that can used while parsing the document
 	StringList template_resources;
 
-	/// Inline RCSS definitions
-	StringList rcss_inline;
-	LineNumberList rcss_inline_line_numbers;
-	/// External RCSS definitions that should be loaded
-	StringList rcss_external;
+	struct Resource {
+		String path; // Content path for inline resources, source path for external resources.
+		String content; // Only set for inline resources.
+		bool is_inline = false;
+		int line = 0;           // Only set for inline resources.
+	};
+	using ResourceList = Vector<Resource>;
 
-	/// Inline script source
-	StringList scripts_inline;
-	/// External scripts that should be loaded
-	StringList scripts_external;
+	/// RCSS definitions
+	ResourceList rcss;
+
+	/// script source
+	ResourceList scripts;
 
 	/// Merges the specified header with this one
 	/// @param header Header to merge
@@ -69,6 +72,9 @@ public:
 
 	/// Merges paths from one string list to another, preserving the base_path
 	void MergePaths(StringList& target, const StringList& source, const String& base_path);
+
+	/// Merges resources
+	void MergeResources(ResourceList& target, const ResourceList& source);
 };
 
 } // namespace Rml

+ 51 - 29
Source/Core/ElementDocument.cpp

@@ -96,28 +96,45 @@ void ElementDocument::ProcessHeader(const DocumentHeader* document_header)
 	// If a style-sheet (or sheets) has been specified for this element, then we load them and set the combined sheet
 	// on the element; all of its children will inherit it by default.
 	SharedPtr<StyleSheet> new_style_sheet;
-	if (header.rcss_external.size() > 0)
-		new_style_sheet = StyleSheetFactory::GetStyleSheet(header.rcss_external);
 
 	// Combine any inline sheets.
-	for (size_t i = 0; i < header.rcss_inline.size(); i++)
+	for (const DocumentHeader::Resource& rcss : header.rcss)
 	{
-		UniquePtr<StyleSheet> inline_sheet = MakeUnique<StyleSheet>();
-		auto stream = MakeUnique<StreamMemory>((const byte*)header.rcss_inline[i].c_str(), header.rcss_inline[i].size());
-		stream->SetSourceURL(document_header->source);
+		if (rcss.is_inline)
+		{
+			UniquePtr<StyleSheet> inline_sheet = MakeUnique<StyleSheet>();
+			auto stream = MakeUnique<StreamMemory>((const byte*)rcss.content.c_str(), rcss.content.size());
+			stream->SetSourceURL(rcss.path);
+
+			if (inline_sheet->LoadStyleSheet(stream.get(), rcss.line))
+			{
+				if (new_style_sheet)
+				{
+					SharedPtr<StyleSheet> combined_sheet = new_style_sheet->CombineStyleSheet(*inline_sheet);
+					new_style_sheet = combined_sheet;
+				}
+				else
+					new_style_sheet = std::move(inline_sheet);
+			}
 
-		if (inline_sheet->LoadStyleSheet(stream.get(), header.rcss_inline_line_numbers[i]))
+			stream.reset();
+		}
+		else
 		{
-			if (new_style_sheet)
+			SharedPtr<StyleSheet> sub_sheet = StyleSheetFactory::GetStyleSheet(rcss.path);
+			if (sub_sheet)
 			{
-				SharedPtr<StyleSheet> combined_sheet = new_style_sheet->CombineStyleSheet(*inline_sheet);
-				new_style_sheet = combined_sheet;
+				if (new_style_sheet)
+				{
+					SharedPtr<StyleSheet> combined_sheet = new_style_sheet->CombineStyleSheet(*sub_sheet);
+					new_style_sheet = std::move(combined_sheet);
+				}
+				else
+					new_style_sheet = sub_sheet;
 			}
 			else
-				new_style_sheet = std::move(inline_sheet);
+				Log::Message(Log::LT_ERROR, "Failed to load style sheet %s.", rcss.path.c_str());
 		}
-
-		stream.reset();
 	}
 
 	// If a style sheet is available, set it on the document and release it.
@@ -126,19 +143,17 @@ void ElementDocument::ProcessHeader(const DocumentHeader* document_header)
 		SetStyleSheet(std::move(new_style_sheet));
 	}
 
-	// Load external scripts.
-	for (size_t i = 0; i < header.scripts_external.size(); i++)
+	// Load scripts.
+	for (const DocumentHeader::Resource& script : header.scripts)
 	{
-		auto stream = MakeUnique<StreamFile>();
-		if (stream->Open(header.scripts_external[i]))
-			LoadScript(stream.get(), header.scripts_external[i]);
-	}
-
-	// Load internal scripts.
-	for (size_t i = 0; i < header.scripts_inline.size(); i++)
-	{
-		auto stream = MakeUnique<StreamMemory>((const byte*) header.scripts_inline[i].c_str(), header.scripts_inline[i].size());
-		LoadScript(stream.get(), "");
+		if (script.is_inline)
+		{
+			LoadInlineScript(script.content, script.path, script.line);
+		}
+		else
+		{
+			LoadExternalScript(script.path);
+		}
 	}
 
 	// Hide this document.
@@ -341,11 +356,18 @@ bool ElementDocument::IsModal() const
 	return modal && IsVisible();
 }
 
-// Default load script implementation
-void ElementDocument::LoadScript(Stream* RMLUI_UNUSED_PARAMETER(stream), const String& RMLUI_UNUSED_PARAMETER(source_name))
+// Default load inline script implementation
+void ElementDocument::LoadInlineScript(const String& RMLUI_UNUSED_PARAMETER(content), const String& RMLUI_UNUSED_PARAMETER(source_path), int RMLUI_UNUSED_PARAMETER(line))
+{
+	RMLUI_UNUSED(content);
+	RMLUI_UNUSED(source_path);
+	RMLUI_UNUSED(line);
+}
+
+// Default load external script implementation
+void ElementDocument::LoadExternalScript(const String& RMLUI_UNUSED_PARAMETER(source_path))
 {
-	RMLUI_UNUSED(stream);
-	RMLUI_UNUSED(source_name);
+	RMLUI_UNUSED(source_path);
 }
 
 // Updates the document, including its layout

+ 6 - 0
Source/Core/Elements/ElementFormControlInput.cpp

@@ -91,6 +91,12 @@ void ElementFormControlInput::OnResize()
 	type->OnResize();
 }
 
+void ElementFormControlInput::OnLayout()
+{
+	RMLUI_ASSERT(type);
+	type->OnLayout();
+}
+
 // Checks for necessary functional changes in the control as a result of changed attributes.
 void ElementFormControlInput::OnAttributeChange(const ElementAttributes& changed_attributes)
 {

+ 4 - 0
Source/Core/Elements/InputType.cpp

@@ -65,6 +65,10 @@ void InputType::OnResize()
 {
 }
 
+void InputType::OnLayout()
+{
+}
+
 // Checks for necessary functional changes in the control as a result of changed attributes.
 bool InputType::OnAttributeChange(const ElementAttributes& RMLUI_UNUSED_PARAMETER(changed_attributes))
 {

+ 3 - 0
Source/Core/Elements/InputType.h

@@ -65,6 +65,9 @@ public:
 	/// Called every time the host element's size changes.
 	virtual void OnResize();
 
+	/// Called every time the host element is layed out.
+	virtual void OnLayout();
+
 	/// Checks for necessary functional changes in the control as a result of changed attributes.
 	/// @param[in] changed_attributes The list of changed attributes.
 	/// @return True if no layout is required, false if the layout needs to be dirtied.

+ 5 - 0
Source/Core/Elements/InputTypeText.cpp

@@ -70,6 +70,11 @@ void InputTypeText::OnResize()
 	widget->OnResize();
 }
 
+void InputTypeText::OnLayout()
+{
+	widget->OnLayout();
+}
+
 // Checks for necessary functional changes in the control as a result of changed attributes.
 bool InputTypeText::OnAttributeChange(const ElementAttributes& changed_attributes)
 {

+ 3 - 0
Source/Core/Elements/InputTypeText.h

@@ -62,6 +62,9 @@ public:
 	/// Called when the parent element's size changes.
 	void OnResize() override;
 
+	/// Called when the parent element is layed out.
+	void OnLayout() override;
+
 	/// Checks for necessary functional changes in the control as a result of changed attributes.
 	/// @param[in] changed_attributes The list of changed attributes.
 	/// @return True if no layout is required, false if the layout needs to be dirtied.

+ 2 - 0
Source/Core/FileInterface.cpp

@@ -66,6 +66,8 @@ bool FileInterface::LoadFile(const String& path, String& out_data)
 		Log::Message(Log::LT_WARNING, "Could only read %zu of %zu bytes from file %s", read_length, length, path.c_str());
 	}
 
+	Close(handle);
+
 	return true;
 }
 

+ 2 - 0
Source/Core/StyleSheetFactory.cpp

@@ -104,6 +104,8 @@ SharedPtr<StyleSheet> StyleSheetFactory::GetStyleSheet(const String& sheet_name)
 	if (!sheet)
 		return nullptr;
 
+	sheet->OptimizeNodeProperties();
+
 	// Add it to the cache, and add a reference count so the cache will keep hold of it.
 	instance->stylesheets[sheet_name] = sheet;
 

+ 31 - 5
Source/Core/XMLNodeHandlerHead.cpp

@@ -39,6 +39,31 @@
 
 namespace Rml {
 
+static String Absolutepath(const String& source, const String& base)
+{
+	String joined_path;
+	::Rml::GetSystemInterface()->JoinPath(joined_path, StringUtilities::Replace(base, '|', ':'), StringUtilities::Replace(source, '|', ':'));
+	return StringUtilities::Replace(joined_path, ':', '|');
+}
+
+static DocumentHeader::Resource MakeInlineResource(XMLParser* parser, const String& data)
+{
+	DocumentHeader::Resource resource;
+	resource.is_inline = true;
+	resource.content = data;
+	resource.path = parser->GetSourceURL().GetURL();
+	resource.line = parser->GetLineNumberOpenTag();
+	return resource;
+}
+
+static DocumentHeader::Resource MakeExternalResource(XMLParser* parser, const String& path)
+{
+	DocumentHeader::Resource resource;
+	resource.is_inline = false;
+	resource.path = Absolutepath(path, parser->GetSourceURL().GetURL());
+	return resource;
+}
+
 XMLNodeHandlerHead::XMLNodeHandlerHead()
 {
 }
@@ -68,7 +93,7 @@ Element* XMLNodeHandlerHead::ElementStart(XMLParser* parser, const String& name,
 			if (type == "text/rcss" ||
 				 type == "text/css")
 			{
-				parser->GetDocumentHeader()->rcss_external.push_back(href);
+				parser->GetDocumentHeader()->rcss.push_back(MakeExternalResource(parser, href));
 			}
 
 			// If its an template, add to the template fields
@@ -95,7 +120,7 @@ Element* XMLNodeHandlerHead::ElementStart(XMLParser* parser, const String& name,
 		String src = Get<String>(attributes, "src", "");
 		if (src.size() > 0)
 		{
-			parser->GetDocumentHeader()->scripts_external.push_back(src);
+			parser->GetDocumentHeader()->scripts.push_back(MakeExternalResource(parser, src));
 		}
 	}
 
@@ -134,13 +159,14 @@ bool XMLNodeHandlerHead::ElementData(XMLParser* parser, const String& data, XMLD
 
 	// Store an inline script
 	if (tag == "script" && data.size() > 0)
-		parser->GetDocumentHeader()->scripts_inline.push_back(data);
+	{
+		parser->GetDocumentHeader()->scripts.push_back(MakeInlineResource(parser, data));
+	}
 
 	// Store an inline style
 	if (tag == "style" && data.size() > 0)
 	{
-		parser->GetDocumentHeader()->rcss_inline.push_back(data);
-		parser->GetDocumentHeader()->rcss_inline_line_numbers.push_back(parser->GetLineNumberOpenTag());
+		parser->GetDocumentHeader()->rcss.push_back(MakeInlineResource(parser, data));
 	}
 
 	return true;

+ 14 - 15
Source/Lua/LuaDocument.cpp

@@ -39,22 +39,21 @@ LuaDocument::LuaDocument(const String& tag) : ElementDocument(tag)
 {
 }
 
-void LuaDocument::LoadScript(Stream* stream, const String& source_name)
+void LuaDocument::LoadInlineScript(const String& context, const String& source_path, int source_line)
 {
-    //if it is loaded from a file
-    if(!source_name.empty())
-    {
-        Interpreter::LoadFile(source_name);
-    }
-    else
-    {
-        String buffer;
-        buffer += "--";
-        buffer += this->GetSourceURL();
-        buffer += "\n";
-        stream->Read(buffer,stream->Length()); //just do the whole thing
-        Interpreter::DoString(buffer, buffer);
-    }
+    String buffer;
+    buffer += "--";
+    buffer += source_path;
+    buffer += ":";
+    buffer += Rml::ToString(source_line);
+    buffer += "\n";
+    buffer += context;
+    Interpreter::DoString(buffer, buffer);
+}
+
+void LuaDocument::LoadExternalScript(const String& source_path)
+{
+    Interpreter::LoadFile(source_path);
 }
 
 } // namespace Lua

+ 3 - 2
Source/Lua/LuaDocument.h

@@ -29,7 +29,7 @@
 #ifndef RMLUI_LUA_LUADOCUMENT_H
 #define RMLUI_LUA_LUADOCUMENT_H
 /*
-    This class is an ElementDocument that overrides the LoadScript function
+    This class is an ElementDocument that overrides the LoadInlineScript and LoadExternalScript function
 */
 #include <RmlUi/Core/ElementDocument.h>
 
@@ -40,7 +40,8 @@ class LuaDocument : public ::Rml::ElementDocument
 {
 public:
     LuaDocument(const String& tag);
-    void LoadScript(Stream* stream, const String& source_name) override;
+    void LoadInlineScript(const String& content, const String& source_path, int source_line) override;
+    void LoadExternalScript(const String& source_path) override;
 };
 
 } // namespace Lua

+ 1 - 1
Tests/Data/VisualTests/issue_143_overflow_in_absolutely_positioned_input.rml

@@ -3,7 +3,7 @@
     <title>Overflow in absolutely positioned input</title>
     <link type="text/rcss" href="../style.rcss"/>
 	<link rel="GitHub issue #143" href="https://github.com/mikke89/RmlUi/issues/143" />
-	<meta name="Description" content="An &lt;input&gt; with a too long value starts out overflowing. When selecting some text in it, then removing the selection (by clicking, arrow key, home/end or taking the focus out) the text does get clipped. Now when something else needs clipping, the &lt;input&gt; overflows again. It only happens when the &lt;input&gt; is position: absolute." />
+	<meta name="Description" content="The contents of input text element (purple) should always be clipped and never overflow. The also applies when hovering the mouse cursor over the designated area." />
 	<style>
 		body {
 			background: #ddd;

+ 2 - 2
Tests/Source/VisualTests/TestViewer.cpp

@@ -216,7 +216,7 @@ bool TestViewer::LoadTest(const Rml::String& directory, const Rml::String& filen
 		if (source_test.empty())
 			return false;
 
-		document_test = context->LoadDocumentFromMemory(source_test, filename);
+		document_test = context->LoadDocumentFromMemory(source_test, Rml::StringUtilities::Replace(test_path, ':', '|'));
 		if (!document_test)
 			return false;
 
@@ -239,7 +239,7 @@ bool TestViewer::LoadTest(const Rml::String& directory, const Rml::String& filen
 
 			if (!source_reference.empty())
 			{
-				document_reference = context->LoadDocumentFromMemory(source_reference, reference_filename);
+				document_reference = context->LoadDocumentFromMemory(source_reference, Rml::StringUtilities::Replace(reference_path, ':', '|'));
 				if (document_reference)
 				{
 					document_reference->SetProperty(PropertyId::Left, Property(510.f, Property::PX));

+ 2 - 0
changelog.md

@@ -136,6 +136,7 @@ Improved Lua plugin in several aspects.
 - Debugger improvements: Sort property names alphabetically. Fix a bug where the outlines would draw underneath the document.
 - Tabs and panels in tab sets will no longer set the `display` property to `inline-block`, thus it is now possible to customize the display property.
 - Add `Rml::GetTextureSourceList()` function to list all image sources loaded in all documents. [#131](https://github.com/mikke89/RmlUi/issues/131)
+- RCSS and scripts are now always loaded in declared order [#144](https://github.com/mikke89/RmlUi/pull/144) (thanks @actboy168).
 
 ### Bug fixes
 
@@ -157,6 +158,7 @@ Improved Lua plugin in several aspects.
 - Tab set elements `tab` and `panel` should now have their `display` property set in the RCSS document, use `display: inline-block` for the same behavior as before.
 - For custom, replaced elements: `Element::GetIntrinsicDimensions()` now additionally takes an intrinsic ratio parameter.
 - The `fill-image` property should now be applied to the \<progressbar\> element instead of its inner \<fill\> element.
+- The function `ElementDocument::LoadScript` is now changed to handle internal and external scripts separately. [#144](https://github.com/mikke89/RmlUi/pull/144)
 
 
 ## RmlUi 3.3