浏览代码

Added window_flushDeferredActions to the GUI API, so that one can get updated lists of child components without drawing the whole interface.

David Piuva 6 月之前
父节点
当前提交
15fca9d2b5

+ 5 - 0
Source/DFPSR/api/guiAPI.cpp

@@ -172,6 +172,11 @@ void dsr::window_drawComponents(const Window& window) {
 	MUST_EXIST(window, window_drawComponents);
 	window->drawComponents();
 }
+void dsr::window_flushDeferredActions(const Window& window) {
+	MUST_EXIST(window, window_flushDeferredActions);
+	window->flushDeferredActions();
+}
+
 void dsr::window_showCanvas(const Window& window) {
 	MUST_EXIST(window, window_showCanvas);
 	window->showCanvas();

+ 9 - 4
Source/DFPSR/api/guiAPI.h

@@ -146,6 +146,13 @@ namespace dsr {
 	// Draw the root component and its children to the canvas.
 	//   Raises an exception if window doesn't exist.
 	void window_drawComponents(const Window& window);
+	// Executes deferred actions without having to call window_drawComponents.
+	// So if you just called component_detachFromParent to remove a child component, this will trigger it instantly
+	//   so that calls to component_getChildCount will show the new count without having to wait for window_drawComponents.
+	// Make sure not to call window_flushDeferredActions from inside of a comonent's event, because that would remove the whole point of deferring actions.
+	//   If an event is triggered from within another event, it can easily cause bugs in the program by not executing transactions one after another.
+	// Raises an exception if window doesn't exist.
+	void window_flushDeferredActions(const Window& window);
 	// Show the canvas.
 	//   Raises an exception if window doesn't exist.
 	void window_showCanvas(const Window& window);
@@ -265,10 +272,8 @@ namespace dsr {
 	Component component_createWithInterfaceFromFile(Component& parent, const String& filename);
 	// Returns true iff the component exists.
 	bool component_exists(const Component& component);
-	// Removed the component from the parent.
-	//   Does nothing if used against the root component.
-	//   Make sure to erase any other references to the component if you want it erased, including parent pointers in any child components that may still be attached unless you detach them first.
-	//   There is currently no attach function, because such a function would need runtime checks against cyclic dependencies from attaching a parent to its own child, and still be hard to debug once it happens.
+	// Marks component as detached, so that it will be safely removed from the parent's list next time window_drawComponents or window_flushDeferredActions is called.
+	//   Deferring the removal makes sure that no event's callback is called from inside of another event.
 	void component_detachFromParent(const Component& component);
 	// Returns the number of direct (non-recursive) child components attached to parent, or -1 if parent is a null handle.
 	int component_getChildCount(const Component& parent);

+ 4 - 0
Source/DFPSR/implementation/gui/DsrWindow.cpp

@@ -248,6 +248,10 @@ void DsrWindow::drawComponents() {
 	this->mainPanel->draw(canvas, IVector2D(0, 0));
 }
 
+void DsrWindow::flushDeferredActions() {
+	this->mainPanel->flushDeferredActions();
+}
+
 AlignedImageRgbaU8 DsrWindow::getCanvas() {
 	auto fullResolutionCanvas = this->backend->getCanvas();
 	if (this->pixelScale > 1) {

+ 2 - 0
Source/DFPSR/implementation/gui/DsrWindow.h

@@ -127,6 +127,8 @@ public:
 		void removeDepthBuffer();
 		// Draw components directly to the canvas in full resolution
 		void drawComponents();
+		// Execute deferred actions once it is safe to trigger callbacks from affected components.
+		void flushDeferredActions();
 		// Show the canvas when an image is ready
 		void showCanvas();
 		// Canvas width in the pre-upscale resolution

+ 9 - 1
Source/DFPSR/implementation/gui/VisualComponent.cpp

@@ -202,9 +202,17 @@ static void drawOverlays(ImageRgbaU8& targetImage, VisualComponent &component, c
 	}
 }
 
+void VisualComponent::flushDeferredActions() {
+	this->sendNotifications();
+	if (!this->managesChildren()) {
+		for (int i = 0; i < this->getChildCount(); i++) {
+			this->children[i]->flushDeferredActions();
+		}
+	}
+}
+
 // Offset may become non-zero when the origin is outside of targetImage from being clipped outside of the parent region
 void VisualComponent::draw(ImageRgbaU8& targetImage, const IVector2D& offset) {
-	// TODO: Any more good places to send notifications to make the GUI respond faster?
 	// When about to start drawing from the root, check for state changes and handle events before drawing,
 	//   so that anything needed for visuals is handled without further delay.
 	if (this->parent == nullptr) {

+ 2 - 0
Source/DFPSR/implementation/gui/VisualComponent.h

@@ -55,6 +55,8 @@ public: // Relations
 	int holdCount = 0;
 	// Marked for removal from the parent when set to true.
 	bool detach = false;
+	// Applying deferred actions before drawing.
+	void flushDeferredActions();
 	// Remember the pressed component for sending mouse move events outside of its region.
 	Handle<VisualComponent> dragComponent;
 private: // States