Browse Source

Made an internal isFocused function for components.

David Piuva 3 years ago
parent
commit
7215b1e01e
2 changed files with 18 additions and 2 deletions
  1. 14 1
      Source/DFPSR/gui/VisualComponent.cpp
  2. 4 1
      Source/DFPSR/gui/VisualComponent.h

+ 14 - 1
Source/DFPSR/gui/VisualComponent.cpp

@@ -187,7 +187,7 @@ void VisualComponent::detachFromParent() {
 	// Check if there's a parent component
 	// Check if there's a parent component
 	VisualComponent *parent = this->parent;
 	VisualComponent *parent = this->parent;
 	if (parent != nullptr) {
 	if (parent != nullptr) {
-		// If the removed component is focused from the parent, then remove focus
+		// If the removed component is focused from the parent, then remove focus so that the parent is focused instead.
 		if (parent->focusComponent.get() == this) {
 		if (parent->focusComponent.get() == this) {
 			parent->focusComponent = std::shared_ptr<VisualComponent>();
 			parent->focusComponent = std::shared_ptr<VisualComponent>();
 		}
 		}
@@ -371,3 +371,16 @@ String VisualComponent::call(const ReadableString &methodName, const ReadableStr
 	throwError("Unimplemented custom call received");
 	throwError("Unimplemented custom call received");
 	return U"";
 	return U"";
 }
 }
+
+bool VisualComponent::isFocused() {
+	if (this->parent != nullptr) {
+		// For child component, go back to the root and then follow the focus pointers to find out which component is focused within the whole tree.
+		//   One cannot just check if the parent points back directly, because old pointers may be left from a previous route.
+		VisualComponent *root = this; while (root->parent != nullptr) { root = root->parent; }
+		VisualComponent *leaf = root; while (leaf->focusComponent.get() != nullptr) { leaf = leaf->focusComponent.get(); }
+		return leaf == this; // Focused if the root component points back to this component.
+	} else {
+		// Root component is focused if it does not redirect its focus to a child component.
+		return this->focusComponent.get() == nullptr; // Focused if no child is focused.
+	}
+}

+ 4 - 1
Source/DFPSR/gui/VisualComponent.h

@@ -191,7 +191,7 @@ public:
 	// A rectangular bound check with location is used by default.
 	// A rectangular bound check with location is used by default.
 	// The caller is responsible for checking if the component is visible when needed.
 	// The caller is responsible for checking if the component is visible when needed.
 	virtual bool pointIsInside(const IVector2D& pixelPosition);
 	virtual bool pointIsInside(const IVector2D& pixelPosition);
-	// Get a reference to the topmost child
+	// Get a pointer to the topmost child
 	// Invisible components are ignored by default, but includeInvisible can be enabled to change that.
 	// Invisible components are ignored by default, but includeInvisible can be enabled to change that.
 	// Returns an empty reference if the pixel position didn't hit anything inside.
 	// Returns an empty reference if the pixel position didn't hit anything inside.
 	// Since the root component might not be heap allocated, it cannot return itself by reference.
 	// Since the root component might not be heap allocated, it cannot return itself by reference.
@@ -215,6 +215,9 @@ public:
 	virtual void changedLocation(const IRect &oldLocation, const IRect &newLocation) {};
 	virtual void changedLocation(const IRect &oldLocation, const IRect &newLocation) {};
 	// Custom call handler to manipulate components across a generic API
 	// Custom call handler to manipulate components across a generic API
 	virtual String call(const ReadableString &methodName, const ReadableString &arguments);
 	virtual String call(const ReadableString &methodName, const ReadableString &arguments);
+	// Returns true iff the component is focused.
+	//   The root component is considered focused if none of its children are focused.
+	bool isFocused();
 };
 };
 
 
 }
 }