Просмотр исходного кода

Add ScrollFlag to control scroll-into-view on document show, see #875

Michael Ragazzon 6 дней назад
Родитель
Сommit
a60d823769

+ 9 - 3
Include/RmlUi/Core/ElementDocument.h

@@ -25,6 +25,11 @@ enum class FocusFlag {
 	Keep,     // Focus the element in the document which last had focus.
 	Auto,     // Focus the first tab element with the 'autofocus' attribute or else the document.
 };
+/** ScrollFlag controls whether an element is scrolled into view when showing the document. */
+enum class ScrollFlag {
+	None, // Never scroll.
+	Auto, // Scroll the focused element into view, if applicable.
+};
 
 /**
     Represents a document in the dom tree.
@@ -70,9 +75,10 @@ public:
 	void PushToBack();
 
 	/// Show the document.
-	/// @param[in] modal_flag Flags controlling the modal state of the document, see the 'ModalFlag' description for details.
-	/// @param[in] focus_flag Flags controlling the focus, see the 'FocusFlag' description for details.
-	void Show(ModalFlag modal_flag = ModalFlag::None, FocusFlag focus_flag = FocusFlag::Auto);
+	/// @param[in] modal_flag Flag controlling the modal state of the document, see the 'ModalFlag' description for details.
+	/// @param[in] focus_flag Flag controlling the focus, see the 'FocusFlag' description for details.
+	/// @param[in] scroll_flag Flag controlling scrolling, see the 'ScrollFlag' description for details.
+	void Show(ModalFlag modal_flag = ModalFlag::None, FocusFlag focus_flag = FocusFlag::Auto, ScrollFlag scroll_flag = ScrollFlag::Auto);
 	/// Hide the document.
 	void Hide();
 	/// Close the document.

+ 2 - 2
Source/Core/ElementDocument.cpp

@@ -346,7 +346,7 @@ void ElementDocument::PushToBack()
 		context->PushDocumentToBack(this);
 }
 
-void ElementDocument::Show(ModalFlag modal_flag, FocusFlag focus_flag)
+void ElementDocument::Show(ModalFlag modal_flag, FocusFlag focus_flag, ScrollFlag scroll_flag)
 {
 	switch (modal_flag)
 	{
@@ -411,7 +411,7 @@ void ElementDocument::Show(ModalFlag modal_flag, FocusFlag focus_flag)
 
 		// Focus the window or element
 		bool focused = focus_element->Focus(true);
-		if (focused && focus_element != this)
+		if (focused && focus_element != this && scroll_flag == ScrollFlag::Auto)
 			focus_element->ScrollIntoView(false);
 	}
 

+ 75 - 0
Tests/Source/UnitTests/ElementDocument.cpp

@@ -353,4 +353,79 @@ TEST_CASE("Modal.FocusWithin")
 	TestsShell::ShutdownShell();
 }
 
+TEST_CASE("ScrollFlag")
+{
+	Context* context = TestsShell::GetContext();
+	REQUIRE(context);
+
+	static const String document_rml = R"(
+<rml>
+<head>
+<title>Demo</title>
+<link type="text/rcss" href="/assets/rml.rcss" />
+<link type="text/rcss" href="/../Tests/Data/style.rcss" />
+<style>
+	body {
+		width: 400px;
+		height: 300px;
+		overflow-y: scroll;
+		background-color: #333;
+	}
+	div {
+		height: 200px;
+		background-color: #c33;
+		margin: 5px 0;
+	}
+</style>
+</head>
+<body>
+	<div/>
+	<div/>
+	<input id="input" type="text" autofocus/>
+	<div/>
+	<div/>
+</body>
+</rml>
+)";
+
+	ElementDocument* document = context->LoadDocumentFromMemory(document_rml);
+	REQUIRE(document);
+	Element* input = document->GetElementById("input");
+	REQUIRE(input);
+
+	constexpr float scroll_y_none = 0.f;
+	constexpr float scroll_y_input = 138.f;
+
+	SUBCASE("Default")
+	{
+		document->Show();
+		CHECK(document->GetScrollTop() == scroll_y_input);
+	}
+	SUBCASE("Auto")
+	{
+		document->Show(ModalFlag::None, FocusFlag::Auto, ScrollFlag::Auto);
+		CHECK(document->GetScrollTop() == scroll_y_input);
+	}
+	SUBCASE("FocusNone")
+	{
+		document->Show(ModalFlag::None, FocusFlag::None, ScrollFlag::Auto);
+		CHECK(document->GetScrollTop() == scroll_y_none);
+	}
+	SUBCASE("FocusDocument")
+	{
+		document->Show(ModalFlag::None, FocusFlag::Document, ScrollFlag::Auto);
+		CHECK(document->GetScrollTop() == scroll_y_none);
+	}
+	SUBCASE("ScrollNone")
+	{
+		document->Show(ModalFlag::None, FocusFlag::Auto, ScrollFlag::None);
+		CHECK(document->GetScrollTop() == scroll_y_none);
+	}
+
+	TestsShell::RenderLoop();
+
+	document->Close();
+	TestsShell::ShutdownShell();
+}
+
 TEST_SUITE_END();