diff --git a/src/plopp/backends/matplotlib/canvas.py b/src/plopp/backends/matplotlib/canvas.py index d23b05fd..ea9ff8e6 100644 --- a/src/plopp/backends/matplotlib/canvas.py +++ b/src/plopp/backends/matplotlib/canvas.py @@ -690,6 +690,14 @@ def panzoom(self, value: Literal['pan', 'zoom'] | None): elif value is None: self.reset_mode() + def back(self): + """Navigate to the previous view in the pan and zoom history.""" + self.fig.canvas.toolbar.back() + + def forward(self): + """Navigate to the next view in the pan and zoom history.""" + self.fig.canvas.toolbar.forward() + def download_figure(self): """ Save the figure to a PNG file via a pop-up dialog. diff --git a/src/plopp/widgets/toolbar.py b/src/plopp/widgets/toolbar.py index 26555272..1b383dd6 100644 --- a/src/plopp/widgets/toolbar.py +++ b/src/plopp/widgets/toolbar.py @@ -66,6 +66,8 @@ def autoscale_axes() -> None: return Toolbar( tools={ "home": tools.HomeTool(autoscale_axes, tooltip="Autoscale axes range"), + "back": tools.BackTool(view.canvas.back), + "forward": tools.ForwardTool(view.canvas.forward), "panzoom": tools.PanZoomTool(view.canvas.panzoom), "save": tools.SaveTool(view.canvas.download_figure), } diff --git a/src/plopp/widgets/tools.py b/src/plopp/widgets/tools.py index e5058c2e..210e54dc 100644 --- a/src/plopp/widgets/tools.py +++ b/src/plopp/widgets/tools.py @@ -152,6 +152,12 @@ def value(self) -> str | None: HomeTool = partial(ButtonTool, icon='home') """Return home tool.""" +BackTool = partial(ButtonTool, icon='arrow-left', tooltip='Back to previous view') +"""Return tool for navigating to the previous view.""" + +ForwardTool = partial(ButtonTool, icon='arrow-right', tooltip='Forward to next view') +"""Return tool for navigating to the next view.""" + SaveTool = partial(ButtonTool, icon='save', tooltip='Save figure') """Save figure to png tool.""" diff --git a/tests/backends/matplotlib/mpl_canvas_test.py b/tests/backends/matplotlib/mpl_canvas_test.py index cda65df9..9cdd7292 100644 --- a/tests/backends/matplotlib/mpl_canvas_test.py +++ b/tests/backends/matplotlib/mpl_canvas_test.py @@ -167,3 +167,22 @@ def test_home_button_rescales_all_axes_sharing_a_figure(): p0.toolbar['home'].callback() assert p1.canvas.yrange == pytest.approx(expected) + + +@pytest.mark.parametrize("ndim", [1, 2]) +def test_back_and_forward_buttons_navigate_view_history(ndim): + da = data_array(ndim=ndim) + p = da.plot() + toolbar = p.canvas.fig.canvas.toolbar + + original_range = p.canvas.xrange + toolbar.push_current() + zoomed_range = (10.0, 20.0) + p.canvas.xrange = zoomed_range + toolbar.push_current() + + p.toolbar['back'].click() + assert p.canvas.xrange == pytest.approx(original_range) + + p.toolbar['forward'].click() + assert p.canvas.xrange == pytest.approx(zoomed_range)