From 0f7254eaf4e2b5956243fe42dfbf0b952fdb7d1a Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 18 Apr 2026 13:34:40 -0400 Subject: [PATCH] Add parent= kwarg to Grid (follow-up to constructor surface freeze) Group A flagged that Grid lacked the parent= kwarg added to all other UI drawables. Grid is also a UIDrawable that can live in a Scene's or Frame's children -- closing the gap for full constructor consistency. Implementation handles parent= uniformly across both Grid init modes: Mode 1 (explicit view of existing GridData): grid=existing_grid Mode 2 (factory mode): grid_size=(w, h) UIGridView::init now strips parent= from the kwds (using a dict copy -- caller's kwds is never mutated), dispatches to the appropriate mode helper, and applies UIDRAWABLE_ATTACH_TO_PARENT on success. The mode-1 inline body moved to a new init_explicit_view helper for clean separation. --- src/UIGridView.cpp | 40 ++++++++++++++++++++++++++++++++++------ src/UIGridView.h | 1 + 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/UIGridView.cpp b/src/UIGridView.cpp index d87d132..d005e6b 100644 --- a/src/UIGridView.cpp +++ b/src/UIGridView.cpp @@ -12,6 +12,7 @@ #include "PyPositionHelper.h" #include "PyVector.h" #include "PythonObjectCache.h" +#include "PySceneObject.h" // parent= kwarg: Scene is a valid parent type #include #include @@ -372,15 +373,45 @@ bool UIGridView::hasProperty(const std::string& name) const int UIGridView::init(PyUIGridViewObject* self, PyObject* args, PyObject* kwds) { + // Extract parent= up front so it doesn't confuse downstream parsing in + // either init mode. parent_obj is borrowed from the original kwds (which + // the caller owns and outlives this function), so no INCREF is needed -- + // but we must not delete from the caller's dict, so make a working copy. + PyObject* parent_obj = nullptr; + PyObject* dispatch_kwds = kwds; + if (kwds) { + parent_obj = PyDict_GetItemString(kwds, "parent"); // borrowed ref + if (parent_obj) { + dispatch_kwds = PyDict_Copy(kwds); + if (!dispatch_kwds) return -1; + PyDict_DelItemString(dispatch_kwds, "parent"); + } + } + // Determine mode by checking for 'grid' kwarg PyObject* grid_kwarg = nullptr; - if (kwds) { - grid_kwarg = PyDict_GetItemString(kwds, "grid"); // borrowed ref + if (dispatch_kwds) { + grid_kwarg = PyDict_GetItemString(dispatch_kwds, "grid"); // borrowed ref } bool explicit_view = (grid_kwarg && grid_kwarg != Py_None); - if (explicit_view) { + int rc = explicit_view + ? init_explicit_view(self, args, dispatch_kwds) + : init_with_data(self, args, dispatch_kwds); + + if (dispatch_kwds != kwds) Py_DECREF(dispatch_kwds); + if (rc != 0) return rc; + + if (parent_obj) { + UIDRAWABLE_ATTACH_TO_PARENT(parent_obj, self); + } + return 0; +} + +int UIGridView::init_explicit_view(PyUIGridViewObject* self, PyObject* args, PyObject* kwds) +{ + { // Mode 1: View of existing grid data static const char* kwlist[] = {"grid", "pos", "size", "zoom", "fill_color", "name", nullptr}; PyObject* grid_obj = nullptr; @@ -454,9 +485,6 @@ int UIGridView::init(PyUIGridViewObject* self, PyObject* args, PyObject* kwds) self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyUIGridViewType; return 0; - } else { - // Mode 2: Factory mode - create UIGrid internally - return init_with_data(self, args, kwds); } } diff --git a/src/UIGridView.h b/src/UIGridView.h index 5a839e7..ee46af7 100644 --- a/src/UIGridView.h +++ b/src/UIGridView.h @@ -86,6 +86,7 @@ public: // Python API // ========================================================================= static int init(PyUIGridViewObject* self, PyObject* args, PyObject* kwds); + static int init_explicit_view(PyUIGridViewObject* self, PyObject* args, PyObject* kwds); static int init_with_data(PyUIGridViewObject* self, PyObject* args, PyObject* kwds); static PyObject* repr(PyUIGridViewObject* self);