We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add API to replace children
### What is the problem or limitation you are having?

Currently, if I use a multi-pages design and create multiple pages (multiple boxes containing multiple widgets), and I want to switch between these pages — between page1_box and page2_box, for example — I need to:
```
main_box.remove(page1_box)
main_box.insert(pos, page2_box)
```

So, not only it's 2 steps to do 1 thing (swap out/replace a child), but I also need to know the right index for the insert, which seems cumbersome to keep track of if I plan on adding/removing a few widgets during runtime.

### Describe the solution you'd like

Add a `.replace()` method to nodes, that will join the likes of `.remove()` .`add()` and `.insert()`, so that we can:
1. Replace a child node in one step;
2. Not have to worry about index numbers.

Example:
`main_box.replace(page1_box, page2_box)`

In other words:
`Box.replace(old_child, new_child)`

This pattern follows the way Python's string replace works — `str.replace(old, new)`.

### Describe alternatives you've considered

Add method to replace its calling node.
`page1_box.replace(page2_box)`

In other words:
`old_child.replace(new_child)`

But this seems to break the existing convention with add, remove and insert.

### Additional context

_No response_

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `core/src/toga/widgets/base.py`
Content:
```
1 from __future__ import annotations
2 
3 from builtins import id as identifier
4 from typing import TYPE_CHECKING
5 
6 from travertino.node import Node
7 
8 from toga.platform import get_platform_factory
9 from toga.style import Pack, TogaApplicator
10 
11 if TYPE_CHECKING:
12     from toga.app import App
13     from toga.window import Window
14 
15 
16 class Widget(Node):
17     _MIN_WIDTH = 100
18     _MIN_HEIGHT = 100
19 
20     def __init__(
21         self,
22         id: str | None = None,
23         style=None,
24     ):
25         """Create a base Toga widget.
26 
27         This is an abstract base class; it cannot be instantiated.
28 
29         :param id: The ID for the widget.
30         :param style: A style object. If no style is provided, a default style
31             will be applied to the widget.
32         """
33         super().__init__(
34             style=style if style else Pack(),
35             applicator=TogaApplicator(self),
36         )
37 
38         self._id = str(id if id else identifier(self))
39         self._window = None
40         self._app = None
41         self._impl = None
42 
43         self.factory = get_platform_factory()
44 
45     def __repr__(self) -> str:
46         return f"<{self.__class__.__name__}:0x{identifier(self):x}>"
47 
48     def __lt__(self, other) -> bool:
49         return self.id < other.id
50 
51     @property
52     def id(self) -> str:
53         """The DOM identifier for the widget.
54 
55         This id can be used to target CSS directives.
56         """
57         return self._id
58 
59     @property
60     def tab_index(self) -> int | None:
61         """The position of the widget in the focus chain for the window.
62 
63         .. note::
64 
65             This is a beta feature. The ``tab_index`` API may change in
66             the future.
67         """
68         return self._impl.get_tab_index()
69 
70     @tab_index.setter
71     def tab_index(self, tab_index: int) -> None:
72         self._impl.set_tab_index(tab_index)
73 
74     def _assert_can_have_children(self):
75         if not self.can_have_children:
76             raise ValueError(f"{type(self).__name__} cannot have children")
77 
78     def add(self, *children: Widget) -> None:
79         """Add the provided widgets as children of this widget.
80 
81         If a child widget already has a parent, it will be re-parented as a
82         child of this widget. If the child widget is already a child of this
83         widget, there is no change.
84 
85         :param children: The widgets to add as children of this widget.
86         :raises ValueError: If this widget cannot have children.
87         """
88         self._assert_can_have_children()
89         for child in children:
90             if child.parent is not self:
91                 # remove from old parent
92                 if child.parent:
93                     child.parent.remove(child)
94 
95                 # Set app and window. This is done *before* changing any parenting
96                 # relationships, so that the widget registry can verify the widget ID is
97                 # unique. App must be set before window to ensure the widget registry
98                 # can be found.
99                 child.app = self.app
100                 child.window = self.window
101 
102                 # add to new parent
103                 super().add(child)
104 
105                 self._impl.add_child(child._impl)
106 
107         # Whatever layout we're a part of needs to be refreshed
108         self.refresh()
109 
110     def insert(self, index: int, child: Widget) -> None:
111         """Insert a widget as a child of this widget.
112 
113         If a child widget already has a parent, it will be re-parented as a
114         child of this widget. If the child widget is already a child of this
115         widget, there is no change.
116 
117         :param index: The position in the list of children where the new widget
118             should be added.
119         :param child: The child to insert as a child of this node.
120         :raises ValueError: If this widget cannot have children.
121         """
122         self._assert_can_have_children()
123         if child.parent is not self:
124             # remove from old parent
125             if child.parent:
126                 child.parent.remove(child)
127 
128             # Set app and window. This is done *before* changing any parenting
129             # relationships, so that the widget registry can verify the widget ID is
130             # unique. App must be set before window to ensure the widget registry
131             # can be found.
132             child.app = self.app
133             child.window = self.window
134 
135             # add to new parent
136             super().insert(index, child)
137 
138             self._impl.insert_child(index, child._impl)
139 
140         # Whatever layout we're a part of needs to be refreshed
141         self.refresh()
142 
143     def remove(self, *children: Widget) -> None:
144         """Remove the provided widgets as children of this node.
145 
146         Any nominated child widget that is not a child of this widget will
147         not have any change in parentage.
148 
149         Refreshes the widget after removal if any children were removed.
150 
151         :param children: The child nodes to remove.
152         :raises ValueError: If this widget cannot have children.
153         """
154         self._assert_can_have_children()
155 
156         removed = False
157         for child in children:
158             if child.parent is self:
159                 removed = True
160                 super().remove(child)
161 
162                 # Remove from the window before removing from the app
163                 # so that the widget can be removed from the app-level registry.
164                 child.window = None
165                 child.app = None
166 
167                 self._impl.remove_child(child._impl)
168 
169         # If we removed something, whatever layout we're a part of needs to be refreshed
170         if removed:
171             self.refresh()
172 
173     def clear(self) -> None:
174         """Remove all child widgets of this node.
175 
176         Refreshes the widget after removal if any children were removed.
177 
178         :raises ValueError: If this widget cannot have children.
179         """
180         self._assert_can_have_children()
181         self.remove(*self.children)
182 
183     @property
184     def app(self) -> App | None:
185         """The App to which this widget belongs.
186 
187         When setting the app for a widget, all children of this widget will be
188         recursively assigned to the same app.
189 
190         :raises ValueError: If this widget is already associated with another app.
191         """
192         return self._app
193 
194     @app.setter
195     def app(self, app: App | None) -> None:
196         # If the widget is already assigned to an app
197         if self._app:
198             if self._app == app:
199                 # If app is the same as the previous app, return
200                 return
201 
202         self._app = app
203         self._impl.set_app(app)
204         for child in self.children:
205             child.app = app
206 
207     @property
208     def window(self) -> Window | None:
209         """The window to which this widget belongs.
210 
211         When setting the window for a widget, all children of this widget will be
212         recursively assigned to the same window.
213 
214         If the widget has a value for :any:`window`, it *must* also have a value for
215         :any:`app`.
216         """
217         return self._window
218 
219     @window.setter
220     def window(self, window: Window | None) -> None:
221         if self.window is not None and window is None:
222             # If the widget is currently in the registry, but is being removed from a
223             # window, remove the widget from the widget registry
224             self.window.app.widgets._remove(self.id)
225         elif self.window is None and window is not None:
226             # If the widget is being assigned to a window for the first time, add it to the widget registry
227             window.app.widgets._add(self)
228 
229         self._window = window
230         self._impl.set_window(window)
231 
232         for child in self.children:
233             child.window = window
234 
235     @property
236     def enabled(self) -> bool:
237         """Is the widget currently enabled? i.e., can the user interact with the widget?"""
238         return self._impl.get_enabled()
239 
240     @enabled.setter
241     def enabled(self, value: bool) -> None:
242         self._impl.set_enabled(bool(value))
243 
244     def refresh(self) -> None:
245         self._impl.refresh()
246 
247         # Refresh the layout
248         if self._root:
249             # We're not the root of the node hierarchy;
250             # defer the refresh call to the root node.
251             self._root.refresh()
252         else:
253             # We can't compute a layout until we have a container
254             if self._impl.container:
255                 super().refresh(self._impl.container)
256                 self._impl.container.refreshed()
257 
258     def focus(self) -> None:
259         """Give this widget the input focus.
260 
261         This method is a no-op if the widget can't accept focus. The ability of a widget
262         to accept focus is platform-dependent. In general, on desktop platforms you can
263         focus any widget that can accept user input, while on mobile platforms focus is
264         limited to widgets that accept text input (i.e., widgets that cause the virtual
265         keyboard to appear).
266         """
267         self._impl.focus()
268
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/core/src/toga/widgets/base.py b/core/src/toga/widgets/base.py
--- a/core/src/toga/widgets/base.py
+++ b/core/src/toga/widgets/base.py
@@ -140,6 +140,30 @@
         # Whatever layout we're a part of needs to be refreshed
         self.refresh()
 
+    def index(self, child: Widget) -> int:
+        """Get the index of a widget in the list of children of this widget.
+
+        :param child: The child widget of interest.
+        :raises ValueError: If the specified child widget is not found in the
+            list of children.
+
+        :returns: Index of specified child widget in children list.
+        """
+        for _ind, _child in enumerate(self._children):
+            if child == _child:
+                return _ind
+        raise ValueError(f"{type(child).__name__} not found")
+
+    def replace(self, old_child: Widget, new_child: Widget) -> None:
+        """Replace an existing child widget with a new child widget.
+
+        :param old_child: The existing child widget to be replaced.
+        :param new_child: The new child widget to be included.
+        """
+        old_child_index = self.index(old_child)
+        self.remove(old_child)
+        self.insert(old_child_index, new_child)
+
     def remove(self, *children: Widget) -> None:
         """Remove the provided widgets as children of this node.

{"golden_diff": "diff --git a/core/src/toga/widgets/base.py b/core/src/toga/widgets/base.py\n--- a/core/src/toga/widgets/base.py\n+++ b/core/src/toga/widgets/base.py\n@@ -140,6 +140,30 @@\n         # Whatever layout we're a part of needs to be refreshed\n         self.refresh()\n \n+    def index(self, child: Widget) -> int:\n+        \"\"\"Get the index of a widget in the list of children of this widget.\n+\n+        :param child: The child widget of interest.\n+        :raises ValueError: If the specified child widget is not found in the\n+            list of children.\n+\n+        :returns: Index of specified child widget in children list.\n+        \"\"\"\n+        for _ind, _child in enumerate(self._children):\n+            if child == _child:\n+                return _ind\n+        raise ValueError(f\"{type(child).__name__} not found\")\n+\n+    def replace(self, old_child: Widget, new_child: Widget) -> None:\n+        \"\"\"Replace an existing child widget with a new child widget.\n+\n+        :param old_child: The existing child widget to be replaced.\n+        :param new_child: The new child widget to be included.\n+        \"\"\"\n+        old_child_index = self.index(old_child)\n+        self.remove(old_child)\n+        self.insert(old_child_index, new_child)\n+\n     def remove(self, *children: Widget) -> None:\n         \"\"\"Remove the provided widgets as children of this node.\n", "issue": "Add API to replace children\n### What is the problem or limitation you are having?\r\n\r\nCurrently, if I use a multi-pages design and create multiple pages (multiple boxes containing multiple widgets), and I want to switch between these pages \u2014 between page1_box and page2_box, for example \u2014 I need to:\r\n```\r\nmain_box.remove(page1_box)\r\nmain_box.insert(pos, page2_box)\r\n```\r\n\r\nSo, not only it's 2 steps to do 1 thing (swap out/replace a child), but I also need to know the right index for the insert, which seems cumbersome to keep track of if I plan on adding/removing a few widgets during runtime.\r\n\r\n### Describe the solution you'd like\r\n\r\nAdd a `.replace()` method to nodes, that will join the likes of `.remove()` .`add()` and `.insert()`, so that we can:\r\n1. Replace a child node in one step;\r\n2. Not have to worry about index numbers.\r\n\r\nExample:\r\n`main_box.replace(page1_box, page2_box)`\r\n\r\nIn other words:\r\n`Box.replace(old_child, new_child)`\r\n\r\nThis pattern follows the way Python's string replace works \u2014 `str.replace(old, new)`.\r\n\r\n### Describe alternatives you've considered\r\n\r\nAdd method to replace its calling node.\r\n`page1_box.replace(page2_box)`\r\n\r\nIn other words:\r\n`old_child.replace(new_child)`\r\n\r\nBut this seems to break the existing convention with add, remove and insert.\r\n\r\n### Additional context\r\n\r\n_No response_\n", "before_files": [{"content": "from __future__ import annotations\n\nfrom builtins import id as identifier\nfrom typing import TYPE_CHECKING\n\nfrom travertino.node import Node\n\nfrom toga.platform import get_platform_factory\nfrom toga.style import Pack, TogaApplicator\n\nif TYPE_CHECKING:\n    from toga.app import App\n    from toga.window import Window\n\n\nclass Widget(Node):\n    _MIN_WIDTH = 100\n    _MIN_HEIGHT = 100\n\n    def __init__(\n        self,\n        id: str | None = None,\n        style=None,\n    ):\n        \"\"\"Create a base Toga widget.\n\n        This is an abstract base class; it cannot be instantiated.\n\n        :param id: The ID for the widget.\n        :param style: A style object. If no style is provided, a default style\n            will be applied to the widget.\n        \"\"\"\n        super().__init__(\n            style=style if style else Pack(),\n            applicator=TogaApplicator(self),\n        )\n\n        self._id = str(id if id else identifier(self))\n        self._window = None\n        self._app = None\n        self._impl = None\n\n        self.factory = get_platform_factory()\n\n    def __repr__(self) -> str:\n        return f\"<{self.__class__.__name__}:0x{identifier(self):x}>\"\n\n    def __lt__(self, other) -> bool:\n        return self.id < other.id\n\n    @property\n    def id(self) -> str:\n        \"\"\"The DOM identifier for the widget.\n\n        This id can be used to target CSS directives.\n        \"\"\"\n        return self._id\n\n    @property\n    def tab_index(self) -> int | None:\n        \"\"\"The position of the widget in the focus chain for the window.\n\n        .. note::\n\n            This is a beta feature. The ``tab_index`` API may change in\n            the future.\n        \"\"\"\n        return self._impl.get_tab_index()\n\n    @tab_index.setter\n    def tab_index(self, tab_index: int) -> None:\n        self._impl.set_tab_index(tab_index)\n\n    def _assert_can_have_children(self):\n        if not self.can_have_children:\n            raise ValueError(f\"{type(self).__name__} cannot have children\")\n\n    def add(self, *children: Widget) -> None:\n        \"\"\"Add the provided widgets as children of this widget.\n\n        If a child widget already has a parent, it will be re-parented as a\n        child of this widget. If the child widget is already a child of this\n        widget, there is no change.\n\n        :param children: The widgets to add as children of this widget.\n        :raises ValueError: If this widget cannot have children.\n        \"\"\"\n        self._assert_can_have_children()\n        for child in children:\n            if child.parent is not self:\n                # remove from old parent\n                if child.parent:\n                    child.parent.remove(child)\n\n                # Set app and window. This is done *before* changing any parenting\n                # relationships, so that the widget registry can verify the widget ID is\n                # unique. App must be set before window to ensure the widget registry\n                # can be found.\n                child.app = self.app\n                child.window = self.window\n\n                # add to new parent\n                super().add(child)\n\n                self._impl.add_child(child._impl)\n\n        # Whatever layout we're a part of needs to be refreshed\n        self.refresh()\n\n    def insert(self, index: int, child: Widget) -> None:\n        \"\"\"Insert a widget as a child of this widget.\n\n        If a child widget already has a parent, it will be re-parented as a\n        child of this widget. If the child widget is already a child of this\n        widget, there is no change.\n\n        :param index: The position in the list of children where the new widget\n            should be added.\n        :param child: The child to insert as a child of this node.\n        :raises ValueError: If this widget cannot have children.\n        \"\"\"\n        self._assert_can_have_children()\n        if child.parent is not self:\n            # remove from old parent\n            if child.parent:\n                child.parent.remove(child)\n\n            # Set app and window. This is done *before* changing any parenting\n            # relationships, so that the widget registry can verify the widget ID is\n            # unique. App must be set before window to ensure the widget registry\n            # can be found.\n            child.app = self.app\n            child.window = self.window\n\n            # add to new parent\n            super().insert(index, child)\n\n            self._impl.insert_child(index, child._impl)\n\n        # Whatever layout we're a part of needs to be refreshed\n        self.refresh()\n\n    def remove(self, *children: Widget) -> None:\n        \"\"\"Remove the provided widgets as children of this node.\n\n        Any nominated child widget that is not a child of this widget will\n        not have any change in parentage.\n\n        Refreshes the widget after removal if any children were removed.\n\n        :param children: The child nodes to remove.\n        :raises ValueError: If this widget cannot have children.\n        \"\"\"\n        self._assert_can_have_children()\n\n        removed = False\n        for child in children:\n            if child.parent is self:\n                removed = True\n                super().remove(child)\n\n                # Remove from the window before removing from the app\n                # so that the widget can be removed from the app-level registry.\n                child.window = None\n                child.app = None\n\n                self._impl.remove_child(child._impl)\n\n        # If we removed something, whatever layout we're a part of needs to be refreshed\n        if removed:\n            self.refresh()\n\n    def clear(self) -> None:\n        \"\"\"Remove all child widgets of this node.\n\n        Refreshes the widget after removal if any children were removed.\n\n        :raises ValueError: If this widget cannot have children.\n        \"\"\"\n        self._assert_can_have_children()\n        self.remove(*self.children)\n\n    @property\n    def app(self) -> App | None:\n        \"\"\"The App to which this widget belongs.\n\n        When setting the app for a widget, all children of this widget will be\n        recursively assigned to the same app.\n\n        :raises ValueError: If this widget is already associated with another app.\n        \"\"\"\n        return self._app\n\n    @app.setter\n    def app(self, app: App | None) -> None:\n        # If the widget is already assigned to an app\n        if self._app:\n            if self._app == app:\n                # If app is the same as the previous app, return\n                return\n\n        self._app = app\n        self._impl.set_app(app)\n        for child in self.children:\n            child.app = app\n\n    @property\n    def window(self) -> Window | None:\n        \"\"\"The window to which this widget belongs.\n\n        When setting the window for a widget, all children of this widget will be\n        recursively assigned to the same window.\n\n        If the widget has a value for :any:`window`, it *must* also have a value for\n        :any:`app`.\n        \"\"\"\n        return self._window\n\n    @window.setter\n    def window(self, window: Window | None) -> None:\n        if self.window is not None and window is None:\n            # If the widget is currently in the registry, but is being removed from a\n            # window, remove the widget from the widget registry\n            self.window.app.widgets._remove(self.id)\n        elif self.window is None and window is not None:\n            # If the widget is being assigned to a window for the first time, add it to the widget registry\n            window.app.widgets._add(self)\n\n        self._window = window\n        self._impl.set_window(window)\n\n        for child in self.children:\n            child.window = window\n\n    @property\n    def enabled(self) -> bool:\n        \"\"\"Is the widget currently enabled? i.e., can the user interact with the widget?\"\"\"\n        return self._impl.get_enabled()\n\n    @enabled.setter\n    def enabled(self, value: bool) -> None:\n        self._impl.set_enabled(bool(value))\n\n    def refresh(self) -> None:\n        self._impl.refresh()\n\n        # Refresh the layout\n        if self._root:\n            # We're not the root of the node hierarchy;\n            # defer the refresh call to the root node.\n            self._root.refresh()\n        else:\n            # We can't compute a layout until we have a container\n            if self._impl.container:\n                super().refresh(self._impl.container)\n                self._impl.container.refreshed()\n\n    def focus(self) -> None:\n        \"\"\"Give this widget the input focus.\n\n        This method is a no-op if the widget can't accept focus. The ability of a widget\n        to accept focus is platform-dependent. In general, on desktop platforms you can\n        focus any widget that can accept user input, while on mobile platforms focus is\n        limited to widgets that accept text input (i.e., widgets that cause the virtual\n        keyboard to appear).\n        \"\"\"\n        self._impl.focus()\n", "path": "core/src/toga/widgets/base.py"}], "after_files": [{"content": "from __future__ import annotations\n\nfrom builtins import id as identifier\nfrom typing import TYPE_CHECKING\n\nfrom travertino.node import Node\n\nfrom toga.platform import get_platform_factory\nfrom toga.style import Pack, TogaApplicator\n\nif TYPE_CHECKING:\n    from toga.app import App\n    from toga.window import Window\n\n\nclass Widget(Node):\n    _MIN_WIDTH = 100\n    _MIN_HEIGHT = 100\n\n    def __init__(\n        self,\n        id: str | None = None,\n        style=None,\n    ):\n        \"\"\"Create a base Toga widget.\n\n        This is an abstract base class; it cannot be instantiated.\n\n        :param id: The ID for the widget.\n        :param style: A style object. If no style is provided, a default style\n            will be applied to the widget.\n        \"\"\"\n        super().__init__(\n            style=style if style else Pack(),\n            applicator=TogaApplicator(self),\n        )\n\n        self._id = str(id if id else identifier(self))\n        self._window = None\n        self._app = None\n        self._impl = None\n\n        self.factory = get_platform_factory()\n\n    def __repr__(self) -> str:\n        return f\"<{self.__class__.__name__}:0x{identifier(self):x}>\"\n\n    def __lt__(self, other) -> bool:\n        return self.id < other.id\n\n    @property\n    def id(self) -> str:\n        \"\"\"The DOM identifier for the widget.\n\n        This id can be used to target CSS directives.\n        \"\"\"\n        return self._id\n\n    @property\n    def tab_index(self) -> int | None:\n        \"\"\"The position of the widget in the focus chain for the window.\n\n        .. note::\n\n            This is a beta feature. The ``tab_index`` API may change in\n            the future.\n        \"\"\"\n        return self._impl.get_tab_index()\n\n    @tab_index.setter\n    def tab_index(self, tab_index: int) -> None:\n        self._impl.set_tab_index(tab_index)\n\n    def _assert_can_have_children(self):\n        if not self.can_have_children:\n            raise ValueError(f\"{type(self).__name__} cannot have children\")\n\n    def add(self, *children: Widget) -> None:\n        \"\"\"Add the provided widgets as children of this widget.\n\n        If a child widget already has a parent, it will be re-parented as a\n        child of this widget. If the child widget is already a child of this\n        widget, there is no change.\n\n        :param children: The widgets to add as children of this widget.\n        :raises ValueError: If this widget cannot have children.\n        \"\"\"\n        self._assert_can_have_children()\n        for child in children:\n            if child.parent is not self:\n                # remove from old parent\n                if child.parent:\n                    child.parent.remove(child)\n\n                # Set app and window. This is done *before* changing any parenting\n                # relationships, so that the widget registry can verify the widget ID is\n                # unique. App must be set before window to ensure the widget registry\n                # can be found.\n                child.app = self.app\n                child.window = self.window\n\n                # add to new parent\n                super().add(child)\n\n                self._impl.add_child(child._impl)\n\n        # Whatever layout we're a part of needs to be refreshed\n        self.refresh()\n\n    def insert(self, index: int, child: Widget) -> None:\n        \"\"\"Insert a widget as a child of this widget.\n\n        If a child widget already has a parent, it will be re-parented as a\n        child of this widget. If the child widget is already a child of this\n        widget, there is no change.\n\n        :param index: The position in the list of children where the new widget\n            should be added.\n        :param child: The child to insert as a child of this node.\n        :raises ValueError: If this widget cannot have children.\n        \"\"\"\n        self._assert_can_have_children()\n        if child.parent is not self:\n            # remove from old parent\n            if child.parent:\n                child.parent.remove(child)\n\n            # Set app and window. This is done *before* changing any parenting\n            # relationships, so that the widget registry can verify the widget ID is\n            # unique. App must be set before window to ensure the widget registry\n            # can be found.\n            child.app = self.app\n            child.window = self.window\n\n            # add to new parent\n            super().insert(index, child)\n\n            self._impl.insert_child(index, child._impl)\n\n        # Whatever layout we're a part of needs to be refreshed\n        self.refresh()\n\n    def index(self, child: Widget) -> int:\n        \"\"\"Get the index of a widget in the list of children of this widget.\n\n        :param child: The child widget of interest.\n        :raises ValueError: If the specified child widget is not found in the\n            list of children.\n\n        :returns: Index of specified child widget in children list.\n        \"\"\"\n        for _ind, _child in enumerate(self._children):\n            if child == _child:\n                return _ind\n        raise ValueError(f\"{type(child).__name__} not found\")\n\n    def replace(self, old_child: Widget, new_child: Widget) -> None:\n        \"\"\"Replace an existing child widget with a new child widget.\n\n        :param old_child: The existing child widget to be replaced.\n        :param new_child: The new child widget to be included.\n        \"\"\"\n        old_child_index = self.index(old_child)\n        self.remove(old_child)\n        self.insert(old_child_index, new_child)\n\n    def remove(self, *children: Widget) -> None:\n        \"\"\"Remove the provided widgets as children of this node.\n\n        Any nominated child widget that is not a child of this widget will\n        not have any change in parentage.\n\n        Refreshes the widget after removal if any children were removed.\n\n        :param children: The child nodes to remove.\n        :raises ValueError: If this widget cannot have children.\n        \"\"\"\n        self._assert_can_have_children()\n\n        removed = False\n        for child in children:\n            if child.parent is self:\n                removed = True\n                super().remove(child)\n\n                # Remove from the window before removing from the app\n                # so that the widget can be removed from the app-level registry.\n                child.window = None\n                child.app = None\n\n                self._impl.remove_child(child._impl)\n\n        # If we removed something, whatever layout we're a part of needs to be refreshed\n        if removed:\n            self.refresh()\n\n    def clear(self) -> None:\n        \"\"\"Remove all child widgets of this node.\n\n        Refreshes the widget after removal if any children were removed.\n\n        :raises ValueError: If this widget cannot have children.\n        \"\"\"\n        self._assert_can_have_children()\n        self.remove(*self.children)\n\n    @property\n    def app(self) -> App | None:\n        \"\"\"The App to which this widget belongs.\n\n        When setting the app for a widget, all children of this widget will be\n        recursively assigned to the same app.\n\n        :raises ValueError: If this widget is already associated with another app.\n        \"\"\"\n        return self._app\n\n    @app.setter\n    def app(self, app: App | None) -> None:\n        # If the widget is already assigned to an app\n        if self._app:\n            if self._app == app:\n                # If app is the same as the previous app, return\n                return\n\n        self._app = app\n        self._impl.set_app(app)\n        for child in self.children:\n            child.app = app\n\n    @property\n    def window(self) -> Window | None:\n        \"\"\"The window to which this widget belongs.\n\n        When setting the window for a widget, all children of this widget will be\n        recursively assigned to the same window.\n\n        If the widget has a value for :any:`window`, it *must* also have a value for\n        :any:`app`.\n        \"\"\"\n        return self._window\n\n    @window.setter\n    def window(self, window: Window | None) -> None:\n        if self.window is not None and window is None:\n            # If the widget is currently in the registry, but is being removed from a\n            # window, remove the widget from the widget registry\n            self.window.app.widgets._remove(self.id)\n        elif self.window is None and window is not None:\n            # If the widget is being assigned to a window for the first time, add it to the widget registry\n            window.app.widgets._add(self)\n\n        self._window = window\n        self._impl.set_window(window)\n\n        for child in self.children:\n            child.window = window\n\n    @property\n    def enabled(self) -> bool:\n        \"\"\"Is the widget currently enabled? i.e., can the user interact with the widget?\"\"\"\n        return self._impl.get_enabled()\n\n    @enabled.setter\n    def enabled(self, value: bool) -> None:\n        self._impl.set_enabled(bool(value))\n\n    def refresh(self) -> None:\n        self._impl.refresh()\n\n        # Refresh the layout\n        if self._root:\n            # We're not the root of the node hierarchy;\n            # defer the refresh call to the root node.\n            self._root.refresh()\n        else:\n            # We can't compute a layout until we have a container\n            if self._impl.container:\n                super().refresh(self._impl.container)\n                self._impl.container.refreshed()\n\n    def focus(self) -> None:\n        \"\"\"Give this widget the input focus.\n\n        This method is a no-op if the widget can't accept focus. The ability of a widget\n        to accept focus is platform-dependent. In general, on desktop platforms you can\n        focus any widget that can accept user input, while on mobile platforms focus is\n        limited to widgets that accept text input (i.e., widgets that cause the virtual\n        keyboard to appear).\n        \"\"\"\n        self._impl.focus()\n", "path": "core/src/toga/widgets/base.py"}]}