|
30 | 30 | from contextlib import ExitStack |
31 | 31 | import inspect |
32 | 32 | import itertools |
| 33 | +import functools |
33 | 34 | import logging |
34 | 35 | from numbers import Integral |
35 | 36 | import threading |
@@ -227,6 +228,67 @@ def get_children(self): |
227 | 228 | *self.legends, |
228 | 229 | *self.subfigs] |
229 | 230 |
|
| 231 | + def get_figure(self, root=None): |
| 232 | + """ |
| 233 | + Return the `.Figure` or `.SubFigure` instance the (Sub)Figure belongs to. |
| 234 | +
|
| 235 | + Parameters |
| 236 | + ---------- |
| 237 | + root : bool, default=True |
| 238 | + If False, return the (Sub)Figure this artist is on. If True, |
| 239 | + return the root Figure for a nested tree of SubFigures. |
| 240 | +
|
| 241 | + .. deprecated:: 3.10 |
| 242 | +
|
| 243 | + From version 3.12 *root* will default to False. |
| 244 | + """ |
| 245 | + if self._root_figure is self: |
| 246 | + # Top level Figure |
| 247 | + return self |
| 248 | + |
| 249 | + if self._parent is self._root_figure: |
| 250 | + # Return early to prevent the deprecation warning when *root* does not |
| 251 | + # matter |
| 252 | + return self._parent |
| 253 | + |
| 254 | + if root is None: |
| 255 | + # When deprecation expires, consider removing the docstring and just |
| 256 | + # inheriting the one from Artist. |
| 257 | + message = ('From Matplotlib 3.12 SubFigure.get_figure will by default ' |
| 258 | + 'return the direct parent figure, which may be a SubFigure. ' |
| 259 | + 'To suppress this warning, pass the root parameter. Pass ' |
| 260 | + '`True` to maintain the old behavior and `False` to opt-in to ' |
| 261 | + 'the future behavior.') |
| 262 | + _api.warn_deprecated('3.10', message=message) |
| 263 | + root = True |
| 264 | + |
| 265 | + if root: |
| 266 | + return self._root_figure |
| 267 | + |
| 268 | + return self._parent |
| 269 | + |
| 270 | + def set_figure(self, fig): |
| 271 | + """ |
| 272 | + .. deprecated:: 3.10 |
| 273 | + Currently this method will raise an exception if *fig* is anything other |
| 274 | + than the root `.Figure` this (Sub)Figure is on. In future it will always |
| 275 | + raise an exception. |
| 276 | + """ |
| 277 | + no_switch = ("The parent and root figures of a (Sub)Figure are set at " |
| 278 | + "instantiation and cannot be changed.") |
| 279 | + if fig is self._root_figure: |
| 280 | + _api.warn_deprecated( |
| 281 | + "3.10", |
| 282 | + message=(f"{no_switch} From Matplotlib 3.12 this operation will raise " |
| 283 | + "an exception.")) |
| 284 | + return |
| 285 | + |
| 286 | + raise ValueError(no_switch) |
| 287 | + |
| 288 | + figure = property(functools.partial(get_figure, root=True), set_figure, |
| 289 | + doc=("The root `Figure`. To get the parent of a `SubFigure`, " |
| 290 | + "use the `get_figure` method.")) |
| 291 | + |
230 | 292 | def contains(self, mouseevent): |
231 | 293 | """ |
232 | 294 | Test whether the mouse event occurred on the figure. |
@@ -2222,7 +2284,7 @@ def __init__(self, parent, subplotspec, *, |
2222 | 2284 |
|
2223 | 2285 | self._subplotspec = subplotspec |
2224 | 2286 | self._parent = parent |
2225 | | - self.figure = parent.figure |
| 2287 | + self._root_figure = parent._root_figure |
2226 | 2288 |
|
2227 | 2289 | # subfigures use the parent axstack |
2228 | 2290 | self._axstack = parent._axstack |
@@ -2503,7 +2565,7 @@ def __init__(self, |
2503 | 2565 | %(Figure:kwdoc)s |
2504 | 2566 | """ |
2505 | 2567 | super().__init__(**kwargs) |
2506 | | - self.figure = self |
| 2568 | + self._root_figure = self |
2507 | 2569 | self._layout_engine = None |
2508 | 2570 |
|
2509 | 2571 | if layout is not None: |
|
0 commit comments