Bladeren bron

Separate modal and focus flags for document (see #40)

Michael Ragazzon 6 jaren geleden
bovenliggende
commit
35a9604f97

+ 4 - 4
Include/RmlUi/Core/Element.h

@@ -572,8 +572,10 @@ protected:
 	void Update(float dp_ratio);
 	void Render();
 
-	/// Forces the element to generate a local stacking context, regardless of the value of its z-index
-	/// property.
+	/// Updates definition, computed values, and runs OnPropertyChange on this element.
+	void UpdateProperties();
+
+	/// Forces the element to generate a local stacking context, regardless of the value of its z-index property.
 	void ForceLocalStackingContext();
 
 	/// Called during the update loop after children are updated.
@@ -616,8 +618,6 @@ protected:
 private:
 	void SetParent(Element* parent);
 
-	void UpdateProperties();
-
 	void DirtyOffset();
 	void UpdateOffset();
 

+ 14 - 11
Include/RmlUi/Core/ElementDocument.h

@@ -41,16 +41,19 @@ class ElementText;
 class StyleSheet;
 
 /**
-	Flags used for displaying the document.
-	   None: No focus, remove modal state.
-	   Focus: Focus the first tab element with the 'autofocus' attribute or else the document.
-	   Modal: Focus the first tab element with the 'autofocus' attribute or else the document, other documents cannot receive focus.
-	   FocusPrevious: Focus the previously focused element in the document.
-	   ModalPrevious: Focus the previously focused element in the document, other documents cannot receive focus.
-	   FocusDocument: Focus the document.
-	   ModalDocument: Focus the document, other documents cannot receive focus.
- */
-enum class FocusFlag { None, Focus, Modal, FocusPrevious, ModalPrevious, FocusDocument, ModalDocument };
+	 ModalFlag used for controlling the modal state of the document.
+		None: Remove modal state.
+		Modal: Set modal state, other documents cannot receive focus.
+		Previous: Modal state unchanged.
+
+	FocusFlag used for displaying the document.
+	   None: No focus.
+	   Document: Focus the document.
+	   Previous: Focus the previously focused element in the document.
+	   Auto: Focus the first tab element with the 'autofocus' attribute or else the document.
+*/
+enum class ModalFlag { None, Modal, Previous };
+enum class FocusFlag { None, Document, Previous, Auto };
 
 
 /**
@@ -91,7 +94,7 @@ public:
 
 	/// Show the document.
 	/// @param[in] focus_flag  Flags controlling the focus, see the 'FocusFlag' description for details.
-	void Show(FocusFlag focus_flag = FocusFlag::Focus);
+	void Show(ModalFlag modal_flag = ModalFlag::None, FocusFlag focus_flag = FocusFlag::Auto);
 	/// Hide the document.
 	void Hide();
 	/// Close the document.

+ 15 - 21
Samples/basic/demo/src/main.cpp

@@ -101,37 +101,31 @@ public:
 			{
 				window2->GetDocument()->Hide();
 			}
-			else if (key_identifier == Rml::Core::Input::KI_Q)
+
+			using Rml::Core::ModalFlag;
+			using Rml::Core::FocusFlag;
+
+			ModalFlag modal_flag = ModalFlag::None;
+			if (event.GetParameter("ctrl_key", 0))
+				modal_flag = ModalFlag::Modal;
+			else if (event.GetParameter("shift_key", 0))
+				modal_flag = ModalFlag::Previous;
+			
+			if (key_identifier == Rml::Core::Input::KI_Q)
 			{
-				window2->GetDocument()->Show(Rml::Core::FocusFlag::None);
+				window2->GetDocument()->Show(modal_flag, FocusFlag::None);
 			}
 			else if (key_identifier == Rml::Core::Input::KI_W)
 			{
-				window2->GetDocument()->Show(Rml::Core::FocusFlag::Focus);
+				window2->GetDocument()->Show(modal_flag, FocusFlag::Document);
 			}
 			else if (key_identifier == Rml::Core::Input::KI_E)
 			{
-				window2->GetDocument()->Show(Rml::Core::FocusFlag::Modal);
+				window2->GetDocument()->Show(modal_flag, FocusFlag::Previous);
 			}
 			else if (key_identifier == Rml::Core::Input::KI_R)
 			{
-				window2->GetDocument()->Show(Rml::Core::FocusFlag::FocusPrevious);
-			}
-			else if (key_identifier == Rml::Core::Input::KI_T)
-			{
-				window2->GetDocument()->Show(Rml::Core::FocusFlag::ModalPrevious);
-			}
-			else if (key_identifier == Rml::Core::Input::KI_Y)
-			{
-				window2->GetDocument()->Show(Rml::Core::FocusFlag::FocusDocument);
-			}
-			else if (key_identifier == Rml::Core::Input::KI_U)
-			{
-				window2->GetDocument()->Show(Rml::Core::FocusFlag::ModalDocument);
-			}
-			else if (key_identifier == Rml::Core::Input::KI_G)
-			{
-				window2->GetDocument()->GetContext()->UnfocusDocument(window2->GetDocument());
+				window2->GetDocument()->Show(modal_flag, FocusFlag::Auto);
 			}
 		}
 		break;

+ 19 - 31
Source/Core/ElementDocument.cpp

@@ -144,6 +144,9 @@ void ElementDocument::ProcessHeader(const DocumentHeader* document_header)
 
 	// Hide this document.
 	SetProperty(PropertyId::Visibility, Property(Style::Visibility::Hidden));
+
+	// Update properties so that e.g. visibility status can be queried properly immediately.
+	UpdateProperties();
 }
 
 // Returns the document's context.
@@ -204,41 +207,33 @@ void ElementDocument::PushToBack()
 		context->PushDocumentToBack(this);
 }
 
-void ElementDocument::Show(FocusFlag focus_flag)
+void ElementDocument::Show(ModalFlag modal_flag, FocusFlag focus_flag)
 {
-	bool autofocus = false;
+	switch (modal_flag)
+	{
+	case Rml::Core::ModalFlag::None:     modal = false; break;
+	case Rml::Core::ModalFlag::Modal:    modal = true;  break;
+	case Rml::Core::ModalFlag::Previous: break;
+	}
+
 	bool focus = false;
+	bool autofocus = false;
 	bool focus_previous = false;
 
 	switch (focus_flag)
 	{
 	case FocusFlag::None:
-		modal = false;
 		break;
-	case FocusFlag::Focus:
+	case FocusFlag::Document:
 		focus = true;
-		autofocus = true;
-		break;
-	case FocusFlag::Modal:
-		focus = true;
-		autofocus = true;
-		modal = true;
 		break;
-	case FocusFlag::FocusPrevious:
+	case FocusFlag::Previous:
 		focus = true;
 		focus_previous = true;
 		break;
-	case FocusFlag::ModalPrevious:
+	case FocusFlag::Auto:
 		focus = true;
-		focus_previous = true;
-		modal = true;
-		break;
-	case FocusFlag::FocusDocument:
-		focus = true;
-		break;
-	case FocusFlag::ModalDocument:
-		focus = true;
-		modal = true;
+		autofocus = true;
 		break;
 	}
 
@@ -341,7 +336,7 @@ ElementPtr ElementDocument::CreateTextNode(const String& text)
 // Is the current document modal
 bool ElementDocument::IsModal() const
 {
-	return modal;
+	return modal && IsVisible();
 }
 
 // Default load script implementation
@@ -445,13 +440,6 @@ void ElementDocument::OnPropertyChange(const PropertyIdSet& changed_properties)
 {
 	Element::OnPropertyChange(changed_properties);
 
-	if (changed_properties.Contains(PropertyId::Visibility) ||
-		changed_properties.Contains(PropertyId::Display))
-	{
-		if (!IsVisible())
-			modal = false;
-	}
-
 	// If the document's font-size has been changed, we need to dirty all rem properties.
 	if (changed_properties.Contains(PropertyId::FontSize))
 		GetStyle()->DirtyPropertiesWithUnitRecursive(Property::REM);
@@ -478,8 +466,8 @@ void ElementDocument::ProcessDefaultAction(Event& event)
 		{
 			if (Element* element = FindNextTabElement(event.GetTargetElement(), !event.GetParameter<bool>("shift_key", false)))
 			{
-				element->Focus();
-				element->ScrollIntoView(false);
+				if(element->Focus())
+					element->ScrollIntoView(false);
 			}
 		}
 		// Process ENTER being pressed on a focusable object (emulate click)

+ 32 - 18
Source/Core/Lua/Document.cpp

@@ -45,28 +45,36 @@ template<> void ExtraInit<Document>(lua_State* L, int metatable_index)
     AddTypeToElementAsTable<Document>(L);
     
     //create the DocumentFocus table
-    lua_getglobal(L,"DocumentFocus");
+    lua_getglobal(L,"DocumentModal");
     if(lua_isnoneornil(L,-1))
     {
         lua_pop(L,1); //pop unsucessful getglobal
         lua_newtable(L); //create a table for holding the enum
-        lua_pushinteger(L,(int)FocusFlag::None);
+        lua_pushinteger(L,(int)ModalFlag::None);
         lua_setfield(L,-2,"None");
-        lua_pushinteger(L,(int)FocusFlag::Focus);
-        lua_setfield(L,-2,"Focus");
-		lua_pushinteger(L, (int)FocusFlag::Modal);
+        lua_pushinteger(L,(int)ModalFlag::Modal);
         lua_setfield(L,-2,"Modal");
-		lua_pushinteger(L, (int)FocusFlag::FocusPrevious);
-		lua_setfield(L, -2, "FocusPrevious");
-		lua_pushinteger(L, (int)FocusFlag::ModalPrevious);
-		lua_setfield(L, -2, "ModalPrevious");
-		lua_pushinteger(L, (int)FocusFlag::FocusDocument);
-		lua_setfield(L, -2, "FocusDocument");
-		lua_pushinteger(L, (int)FocusFlag::ModalDocument);
-		lua_setfield(L, -2, "ModalDocument");
-        lua_setglobal(L,"DocumentFocus");
-        
+		lua_pushinteger(L, (int)ModalFlag::Previous);
+        lua_setfield(L,-2,"Previous");
+        lua_setglobal(L,"DocumentModal");
     }
+
+	//create the DocumentFocus table
+	lua_getglobal(L, "DocumentFocus");
+	if (lua_isnoneornil(L, -1))
+	{
+		lua_pop(L, 1); //pop unsucessful getglobal
+		lua_newtable(L); //create a table for holding the enum
+		lua_pushinteger(L, (int)FocusFlag::None);
+		lua_setfield(L, -2, "None");
+		lua_pushinteger(L, (int)FocusFlag::Document);
+		lua_setfield(L, -2, "Document");
+		lua_pushinteger(L, (int)FocusFlag::Previous);
+		lua_setfield(L, -2, "Modal");
+		lua_pushinteger(L, (int)FocusFlag::Auto);
+		lua_setfield(L, -2, "Auto");
+		lua_setglobal(L, "DocumentFocus");
+	}
 }
 
 //methods
@@ -87,11 +95,17 @@ int DocumentShow(lua_State* L, Document* obj)
     int top = lua_gettop(L);
     if(top == 0)
         obj->Show();
-    else
+    else if(top == 1)
     {
-        FocusFlag flag = (FocusFlag)luaL_checkinteger(L,1);
-        obj->Show(flag);
+        ModalFlag modal = (ModalFlag)luaL_checkinteger(L,1);
+        obj->Show(modal);
     }
+	else
+	{
+        ModalFlag modal = (ModalFlag)luaL_checkinteger(L,1);
+		FocusFlag focus = (FocusFlag)luaL_checkinteger(L,2);
+		obj->Show(modal, focus);
+	}
     return 0;
 }
 

+ 20 - 9
readme.md

@@ -275,18 +275,29 @@ Some relevant changes for users:
 
 ### Focus flags, autofocus
 
-Elements with property `tab-index: auto;` and the `autofocus` attribute set on them can receive focus when showing a document, `ElementDocument::Show(FocusFlag focus_flag)`. This behavior can be controlled with the new document focus flags:
+It is now possible to autofocus on elements when showing a document. By default, the first element with the property `tab-index: auto;` as well as the attribute `autofocus` set, will receive focus.
 
+The focus behavior as well as the modal state can be controlled with two new separate flags.
+```C++
+ElementDocument::Show(ModalFlag modal_flag = ModalFlag::None, FocusFlag focus_flag = FocusFlag::Auto);
 ```
-enum class FocusFlag { None, Focus, Modal, FocusPrevious, ModalPrevious, FocusDocument, ModalDocument };
 
-None: No focus, remove modal state.
-Focus: Focus the first tab element with the 'autofocus' attribute or else the document.
-Modal: Focus the first tab element with the 'autofocus' attribute or else the document, other documents cannot receive focus.
-FocusPrevious: Focus the previously focused element in the document.
-ModalPrevious: Focus the previously focused element in the document, other documents cannot receive focus.
-FocusDocument: Focus the document.
-ModalDocument: Focus the document, other documents cannot receive focus.
+The flags are specified as follows:
+```C++
+/**
+	 ModalFlag used for controlling the modal state of the document.
+		None: Remove modal state.
+		Modal: Set modal state, other documents cannot receive focus.
+		Previous: Modal state unchanged.
+
+	FocusFlag used for displaying the document.
+	   None: No focus.
+	   Document: Focus the document.
+	   Previous: Focus the previously focused element in the document.
+	   Auto: Focus the first tab element with the 'autofocus' attribute or else the document.
+*/
+enum class ModalFlag { None, Modal, Previous };
+enum class FocusFlag { None, Document, Previous, Auto };
 ```