Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions spatialmath/base/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"plot_cone": "graphics",
"plot_cuboid": "graphics",
"axes_logic": "graphics",
"set_window_title": "graphics",
"plotvol2": "graphics",
"plotvol3": "graphics",
"expand_dims": "graphics",
Expand Down Expand Up @@ -391,6 +392,7 @@ def __getattr__(name):
"plot_cone",
"plot_cuboid",
"axes_logic",
"set_window_title",
"expand_dims",
"isnotebook",
# spatial.base.numeric
Expand Down
34 changes: 34 additions & 0 deletions spatialmath/base/graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,37 @@ def expand_dims(dim: ArrayLike = None, nd: int = 2) -> NDArray:
else:
raise ValueError("nd is 2 or 3")

def set_window_title(fig: plt.Figure, title: str) -> bool:
"""
Set the title of the window containing a figure, if it has one

:param fig: the figure
:type fig: Figure
:param title: the window title
:type title: str
:return: True if the title was set
:rtype: bool

A figure has a window only if it is managed by pyplot and the backend
provides one. A figure on a headless backend such as ``Agg``, or one
created directly with ``matplotlib.figure.Figure``, does not, and then
nothing is done and False is returned.

Example::

>>> from spatialmath.base import plotvol2, set_window_title
>>> ax = plotvol2(5)
>>> set_window_title(ax.figure, "my plot")

.. note:: The title of the window is not the title of the axes, see
:meth:`matplotlib.axes.Axes.set_title`.
"""
manager = getattr(fig.canvas, "manager", None)
if manager is not None and hasattr(manager, "set_window_title"):
manager.set_window_title(title)
return True
return False

def isnotebook() -> bool:
"""
Determine if code is being run from a Jupyter notebook
Expand Down Expand Up @@ -1849,3 +1880,6 @@ def plot_cone(*args, **kwargs) -> None:

def plot_cylinder(*args, **kwargs) -> None:
raise NotImplementedError("Matplotlib is not installed: pip install matplotlib")

def set_window_title(*args, **kwargs) -> None:
raise NotImplementedError("Matplotlib is not installed: pip install matplotlib")
33 changes: 33 additions & 0 deletions tests/base/test_graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,39 @@
# TODO check they actually create artists


class TestWindowTitle(unittest.TestCase):
def teardown_method(self, method):
plt.close("all")

def test_sets_the_title_of_a_managed_figure(self):
from types import SimpleNamespace
from unittest import mock

manager = mock.Mock()
fig = SimpleNamespace(canvas=SimpleNamespace(manager=manager))
self.assertTrue(set_window_title(fig, "a title"))
manager.set_window_title.assert_called_once_with("a title")

def test_pyplot_figure(self):
# the Agg manager has no window, but does accept a title
fig = plt.figure()
self.assertIsInstance(set_window_title(fig, "a title"), bool)

def test_figure_without_a_manager(self):
from matplotlib.figure import Figure

self.assertFalse(set_window_title(Figure(), "a title"))

def test_manager_without_the_method(self):
from types import SimpleNamespace

class Manager:
pass

fig = SimpleNamespace(canvas=SimpleNamespace(manager=Manager()))
self.assertFalse(set_window_title(fig, "a title"))


class TestGraphics(unittest.TestCase):
def teardown_method(self, method):
plt.close("all")
Expand Down
Loading